Typescript using IRange<Timestamp> and timezone format

Following this thread, I’m gonna explain the problem and the solutions I’ve tried so far without any success.

First, the problem:
In workshop when using a typescript function (3 Dimensional Aggregation: IRange, string, Double) to be used in the widget Chart X/Y, we have a difference between the native view and the one using the typescript function:


We have the visualisation shifted by 2 hours which is the difference between the UTC and my timezone.

The attempted solutions:
First I tried to replace the IRange by a string output (string, string, Double) but the results was disappointing:

Then the second option was to put only timestamp in the 3 dimensional output but the output isn’t fitted: “Type ‘Timestamp’ does not satisfy the constraint ‘BucketKey’.”

Now the code: I can’t put everything here but here is what I have:

sortedBuckets.forEach(sortedBucket => {
    const mappedValues = sortedBucket.value.map(item => ({
        key: facilityIdToName.get(item.key) || item.key, // Map skywiseFacilityId to name
        value: item.value
    }));
    output.push({ key: sortedBucket.key, value: mappedValues });
}

my sortedBuckets is the result of an aggregation:

const sortedBuckets =  obj.groupBy(o => o.timestamp.byMonth()).segmentBy(o => o.skywiseFacilityId.topValues()).sum(o => o.value);

From my perspective I think the problem is coming from the IRange or how the workshop is reading it since for the timestamp in typescript we have:

(alias) class Timestamp
import Timestamp
Type representing an instant in time. Can be used as an input or output for a TypeScript function. Offset is always UTC+00:00 for inputs and object properties.

If you have anything else I can try, I’m open to it

Hi, not sure if workshop end has the ability to directly render utc IRange in a different timezone, but from functions we can definitely cast UTC timestamp to the arbitrary timezone you would like to render your timestamps as

// example implementation of a function that "applies timezone" to Timestamp
function applyTimezoneToUtcTimestamp(utcTimestamp: Timestamp, timezone: string ="GST"): Timestamp {
    switch (timezone) {
        case "UTC":
            return utcTimestamp;
        case "GST":
            return utcTimestamp.minusHours(2);
        default:
            throw Error(`The provided timezone "${timezone}" is not supported.`);
    }
}

Next, to apply timezone using the above function to the ThreeDimensionalAggregation that you would like to return from functions, first note that the key of your aggregation is of type IRange, which is defined as:

// in Code repo, class definition can be accessed by Command + LeftClick (MacOS) on the class
export type IRangeable = Double | Integer | Timestamp | LocalDate;
export type IRange<T extends IRangeable> = { min: T; max?: T } | { min?: T; max: T };

which you can see is a simple javascript object containing a min and a max indicating the left and right bounds of the range.

Therefore you can manipulate the content of the ThreeDimensionalAggregation Key (in our case IRange<Timestamp>) like the below

sortedBuckets.forEach(sortedBucket => {
    const key = sortedBucket.key;
    const keyWithTimezone = {
        min: applyTimezoneToUtcTimestamp(key.min!, "YOUR_TIMEZONE"),
        max: applyTimezoneToUtcTimestamp(key.max!, "YOUR_TIMEZONE")
    }
    // continue with the key that is timezone-adjusted ...
});

Could you give this a try and let me know if you still run into issue

Hi,

I’ve tried the solution you’ve proposed and it works.

Both of them are now aligned.
There are still some points to improve it even further:

  • I have to get the timezone of the user to realign the second graph with the first one.
    If there is a way to get that in a way from Workshop or directly in Typescript that would help to solve that part

  • We did changes in the Ontology so that everyone will be on the same ground regardless of their timezone and to still have to take that into consideration in the typescript functions makes it more keen to errors and increase the complexity of it.
    Is there a possibility to implement an option to deactivate the offset from the user when the widget Chart X/Y is using a typescript function.

As a solution I came up with a function that will be flexible through the front-end (Workshop):

import { DateTime } from 'luxon';
...
public static applyTimezoneToUtcTimestamp(utcTimestamp: Timestamp, timezone: string ="UTC"): Timestamp {
  // Function to get the UTC offset in hours for a specific timezone
  function getUTCOffsetForTimezone(zone: string, date: Date = new Date()): number {
      const dt = DateTime.fromJSDate(date).setZone(zone);
      return dt.offset / 60; // offset in hours
  }
  switch (timezone) {
      case "UTC":
          return utcTimestamp;
      case "Europe/Paris":
          return utcTimestamp.minusHours(getUTCOffsetForTimezone(timezone, new Date(utcTimestamp.toISOString())));
      case "Europe/London":
          return utcTimestamp.minusHours(getUTCOffsetForTimezone(timezone, new Date(utcTimestamp.toISOString())));
      case "Asia/Shanghai":
          return utcTimestamp.minusHours(getUTCOffsetForTimezone(timezone, new Date(utcTimestamp.toISOString())));
      case "America/Chicago":
          return utcTimestamp.minusHours(getUTCOffsetForTimezone(timezone, new Date(utcTimestamp.toISOString())));
      default:
          throw Error(`The provided timezone "${timezone}" is not supported.`);
  }
}    

This way we can change dynamically the timezone offset and being exact with the summer / winter time.of certain impacted countries.

1 Like