How to check Daylight Saving Time with Temporal in Javascript?

292 Views Asked by At

In case I have a Date and I want to check if the time is DST I can use a method, such as the following:

function isDST(d) {
  let jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset();
  let jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset();
  return Math.max(jan, jul) != d.getTimezoneOffset();    
}

(source here)

In case I use MomentJS library I reach the same in this way:

moment().isDST();

Anyone knows how to do the same with the upcoming Temporal?

2

There are 2 best solutions below

6
s.Bergmann On BEST ANSWER

the temporal api has a offsetNanoseconds read-only property

zdt = Temporal.ZonedDateTime.from('2020-11-01T01:30-07:00[America/Los_Angeles]');
zdt.offsetNanoseconds;
  // => -25200000000000

also there's the with method which returns a new object with specified field being overwritten.

i have to admit i haven't tested it but something like this should basically be the equivalent to your function. (month index starts at 1)

function isDST(d) {
  let jan = d.with({month: 1}).offsetNanoseconds ;
  let jul = d.with({month: 7}).offsetNanoseconds ;

  return Math.min(jan, jul) != d.offsetNanoseconds ;    
}

zoned DateTime

refine dev

web dev simplified

1
ptomato On

I'd recommend not doing this, at least not in this form.

Aside from the Ireland example mentioned in the comment, there are other time zone jurisdictions where there are one-time or non-semiannual changes in the offset from UTC that occurred for other reasons than DST, and any possible isDST() implementation will, by definition, malfunction in these cases. Another example is that Morocco observes year-round DST except during the month of Ramadan. For most of the world's population, "DST" has no meaning at all.

To solve this, I'd start by asking what you are going to use the information for?

If it's, for example, to specify "Daylight" or "Standard" time in the name of a time zone, you could instead use Intl.DateTimeFormat with the { timeZoneName: 'long' } option, which will give you the name of the time zone with this information included.

If you need it as a drop-in replacement for Moment's isDST() method so that you can port an existing system from Moment to Temporal, I'd recommend reimplementing the Moment function exactly, and plan to move away from the concept of "is DST" in the future. (Note, that the Moment documentation also describes this function as a hack that sometimes doesn't provide correct information.)

The body of the Moment function can be found here and the equivalent for Temporal would be:

function isDST(zdt) {
    return (
        zdt.offsetNanoseconds > zdt.with({ month: 1 }).offsetNanoseconds ||
        zdt.offsetNanoseconds > zst.with({ month: 6 }).offsetNanoseconds
    );
}

Another thing that you might need this information for is to interface with other systems that include an "is DST" bit in their data model (which is an incorrect concept, but you might have no choice.) In this case I'd recommend restricting the "is DST" function to a list of allowed time zones that are known to employ the concept of "DST" and returning false in other cases, which should at least filter out some of the false positives.

if (!listOfTimeZoneIDsWithDST.includes(zdt.timeZone.id))
  return false;