jquense / date-math

simple date math module
MIT License
54 stars 12 forks source link

DTS fix breaks minutes add #18

Open Andries-Smit opened 5 years ago

Andries-Smit commented 5 years ago

When adding a view minutes it it works, the add function works well, though when adding many, like a day, it fails. see test case below

var dateArithmetic = require("date-arithmetic")
var d = new Date(2014, 1, 18, 8, 26, 30, 5);
var dExpect = new Date(2014, 1, 19, 8, 26, 30, 5);
console.log(d); // Tue Feb 18 2014 08:26:30 GMT+0100 (Central European Standard Time)
var addMinutes = function(d, m){
    return new Date(d.getTime() + m * 60 * 1000);
}
var dMin = dateArithmetic.add(d, (24 * 60 ), "minutes");
console.log(dMin, +dExpect === +dMin); // Thu Feb 20 2014 09:26:30 GMT+0100 (Central European Standard Time) , false
var dMin2 = addMinutes(d, (24 * 60 ));
console.log(dMin2); // Wed Feb 19 2014 08:26:30 GMT+0100 (Central European Standard Time)
console.log(dMin, +dExpect === +dMin2); // Thu Feb 20 2014 09:26:30 GMT+0100 (Central European Standard Time), true

The issue, was initiated by https://github.com/jquense/date-math/blob/master/index.js#L225-L228

jquense commented 5 years ago

happy to take a fix if you have one!

jeanlazarou commented 4 years ago

The implementation (v4.1.0) of "add" is failing when using time at the moment when DST begins or ends (tests performed in Europe/Brussels timezone).

As "react-big-calendar" uses this library it breaks when a user is trying to add a timeslot the day DST begins.

Perhaps, "add" should require UTC times because they never change.

jquense commented 4 years ago

happy to take PRs!

jeanlazarou commented 4 years ago

Before providing any fix we need to know what are the use cases.

Say, d is a time the day DST begins, 1:45am, if we want to add 30 minutes to d, what would you expect?

If we take timezone into account, it should be 3:15am even if it looks strange (the same addition the day before would produce 2:15am). It is even stranger the day DST ends (2:45 + 30 min = 2:15 or 3:15 depending on whether you ask for the addition the first time we go to 3am or the second time - human weirdness).

I do not directly use the function therefore I cannot say what people do really expect, but I would say that it should work without being burdened by timezone concerns.

jquense commented 4 years ago

unfortunately i don't think there is a more correct answer :/ In general it probably makes sense to add as normal assuming the 2am is missing, but i honestly don't now myself. How do more robust date libraries handle this like moment?

jeanlazarou commented 4 years ago

I ran next code.

let m = null;

console.log("** Using Date **");
console.log("The day DST begins");
m = new Date("2020-03-29T01:00");
console.log("  " + m);
m = new Date(+m + 30 * 60 * 1000);
console.log("  " + m);
m = new Date(+m + 30 * 60 * 1000);
console.log("  " + m);
m = new Date(+m + 30 * 60 * 1000);
console.log("  " + m);
m = new Date(+m + 30 * 60 * 1000);
console.log("  " + m);

console.log("The day DST ends");
m = new Date("2020-10-25T02:00");
console.log("  " + m);
m = new Date(+m + 30 * 60 * 1000);
console.log("  " + m);
m = new Date(+m + 30 * 60 * 1000);
console.log("  " + m);
m = new Date(+m + 30 * 60 * 1000);
console.log("  " + m);
m = new Date(+m + 30 * 60 * 1000);
console.log("  " + m);

My system is configured in Europe/Brussels, the results are produced with FireFox. The code sets first a date the day DST begins and then when the day DST ends in the Europe/Brussels timezone.

** Using Date **
The day DST begins
  Sun Mar 29 2020 01:00:00 GMT+0100 (Central European Standard Time)
  Sun Mar 29 2020 01:30:00 GMT+0100 (Central European Standard Time)
  Sun Mar 29 2020 03:00:00 GMT+0200 (Central European Summer Time)
  Sun Mar 29 2020 03:30:00 GMT+0200 (Central European Summer Time)
  Sun Mar 29 2020 04:00:00 GMT+0200 (Central European Summer Time)
The day DST ends
  Sun Oct 25 2020 02:00:00 GMT+0200 (Central European Summer Time)
  Sun Oct 25 2020 02:30:00 GMT+0200 (Central European Summer Time)
  Sun Oct 25 2020 02:00:00 GMT+0100 (Central European Standard Time)
  Sun Oct 25 2020 02:30:00 GMT+0100 (Central European Standard Time)
  Sun Oct 25 2020 03:00:00 GMT+0100 (Central European Standard Time)

Same results with moment and moment-timezone (for instance moment.tz("2020-03-08T01:00", "America/Chicago") to set the day DST begins in 2020 in Chicago).

The day DST begins, adding 30 minutes at 1.30am it jumps at 3am. The day DST ends, adding 30 minutes at 2.30am it goes back to 2am and second time goes to 3am.

The Date object (or the moment when using the moment library) behaves like if it keeps the UTC time internally (or the epoch time...).