0

I have the following test which works locally but fails in CI

import { toDate } from "date-fns-tz"
import { parseISO } from "date-fns"

export function isDST(date) {
  const january = new Date(date.getFullYear(), 0, 1).getTimezoneOffset()
  const july = new Date(date.getFullYear(), 6, 1).getTimezoneOffset()

  return Math.max(january, july) !== date.getTimezoneOffset()
}

// Fails
// Expected: true
// Received: false
it("returns true if dst applies", () => {
  const date = toDate(parseISO("2021-03-28 02:00:00"), {
    timeZone: "Europe/Amsterdam",
  })

  expect(isDST(date)).toEqual(true)
})

it("returns false if dst does not apply", () => {
  const date = toDate(parseISO("2021-10-31 03:00:00"), {
    timeZone: "Europe/Amsterdam",
  })

  expect(isDST(date)).toEqual(false)
})

How can I make this function work universally? I tried to apply toDate from date-fns-tz to the dates inside isDST but without success, I also tried to switch to parseISO instead

  • 1
    What is the function supposed to do? How does it fail? Where/what is "CI"? `new Date("March 28, 2021 02:00:00")` is not a good idea, see [*Why does Date.parse give incorrect results?*](https://stackoverflow.com/questions/2587345/why-does-date-parse-give-incorrect-results) – RobG Sep 07 '21 at 20:25
  • It should return true when Daylight Saving Time applies for given date, otherwise false, CI = inside my GitHub workflow, I edited the question with another attempt (related to Date.parse) –  Sep 08 '21 at 06:47
  • 1
    The *isDST* function is treating the dates as local to the host (`new Date(date.getFullYear(), 0, 1)`), so you're just getting whether the host has DST or not, not the objects you're building with date-fns. If you're running the function on GitHub, likely it's set to UTC so *isDST* always returns false. – RobG Sep 08 '21 at 09:24
  • How could I possibly fix this? I thought `getTimezoneOffset` from `date-fns-tz` could help `const january = getTimezoneOffset(timeZone, new Date(date.getUTCFullYear(), 0, 1))` –  Sep 08 '21 at 09:28
  • Just to throw this in here… why do you really care? What's the use case for knowing whether it's DST or not? More often than not this hints at caring too much about details of timekeeping, which you should simply handle a lot more abstractly by using proper library functions and timezone identifiers. I mean, sure, it's a valid question to ask whether DST is active at a certain time or not, but when do you really need to know this information? – deceze Sep 08 '21 at 09:31
  • @deceze You can check my use case [here](https://sourceb.in/UOLWbrVkO7), `openingHour` at the time of calling only contains a day string like `fri` and `from: hh:mm:ss` `to: hh:mm:ss` –  Sep 08 '21 at 09:36
  • ‍♂️ That's hardly informative. You seem to just want to calculate some business hours. I'm not seeing a reason to specifically figure out whether it's DST or not. – deceze Sep 08 '21 at 09:38
  • I only have a day string stored in my database and times so I am trying to get the soonest date from given day and I'm adding the times to it to form a proper date object, but when adding the times I need to be aware of DST –  Sep 08 '21 at 09:39
  • Why do you think you need to be aware of DST in this case? You usually handle this kind of thing at the abstraction level of timezones and let a capable library figure out the details: `get_date(2021, 9, 8, 15, 00, 'Europe/Amsterdam')` (for some fictional "`get_date`" function). It will produce a proper date object or UNIX timestamp, taking into account whether it's DST in Amsterdam on Sept. 8th or not. – deceze Sep 08 '21 at 09:41
  • You would only need to really know whether it's DST at some given time if you're a) writing a low-level library that does time and timezone calculations, and you really don't want to be doing that, since this is a very complex field and this wheel has already been invented often enough. Or you b) need to display to your user "DST is in effect" for whatever reason, and you probably don't need that. – deceze Sep 08 '21 at 09:44
  • I can't recommend this highly enough: https://youtu.be/-5wpm-gesOY – deceze Sep 08 '21 at 09:46
  • Thanks, I will attempt to rewrite the implementation –  Sep 08 '21 at 09:51

1 Answers1

0

@deceze Why you may need to know if a Date & Time String is with Daylight Saving or not. Here is a German Date (with Timezone Info):

    1. Oktober 2022 02:31 Europe/Berlin

What time is that in UTC? You can‘t say! Since Summertime ends at that Sunday. After 30. Oktober 2022 02:59 CEST you will have 30. Oktober 2022 02:00 CET as the next timestamp. I.e. you can have two timestamps which only can be differentiated by the Daylight Saving Times Flag:

  1. 30 Oktober 2022 02:00 CEST
  2. 30 Oktober 2022 02:00 CET … 1h later

That is what you would read on a wall clock. If you don‘t use the Offset Info you cannot convert that timestamp correctly to UTC. That is the reason, why you should always use ISO8601 timestamps WITH offset info or correct Timezone Abbreviations. Only then your date is not ambiguous. And when you want to print the date exactly as on a wall clock, you need to know wether your timestamp has DST or not. You print the timestamp and when it is DST you write CEST otherwise you write CET.

In fact without the timezone abbreviation you cannot convert any timestamp during summertime since you do not know if it is one hour off (CEST) or not (CET).