moment-timezone icon indicating copy to clipboard operation
moment-timezone copied to clipboard

Display issue on DST transition day

Open guidsen opened this issue 6 years ago • 4 comments

const moment1 = moment('2018-03-25')
  .startOf('day')
  .hour(12);

const moment2 = moment('2018-03-25')
  .startOf('day')
  .minute(12 * 60); // Here I'm adding 12 hours in minutes

Output:

moment1: Sun Mar 25 2018 12:00:00 GMT+0200
moment2: Sun Mar 25 2018 13:00:00 GMT+0200

2018-03-25 is the day when the summertime will be activated. Why is the output different? When using 2018-03-25 (the day after), both dates are exactly the same.

Is there a difference between using the .hour and .minute method?

guidsen avatar Mar 20 '18 10:03 guidsen

Hi @guidsen! These methods - .hour() and .minute() are for setting hours and minutes exactly to values you provide, not for adding hours and minutes to the original date.

So, this moment('2018-03-25').startOf('day').hour(12) returns exactly 12:00 on Mar 25 Sun Mar 25 2018 12:00:00 GMT+0200 because explicitly provided .hour(12) means that user wants exacly 12:00 local time.

To add hours or minutes, you should use .add(). Functions .add(12, 'hour') and .add(12 * 60, 'minute') both return the same date - Sun Mar 25 2018 13:00:00 GMT+0200

Of course it's still confusing that that .minute() behaves differently, but I think .minute() was supposed to be used with values from 0 to 59

ellenaua avatar Apr 15 '18 16:04 ellenaua

similar issue occurs with add as well.

 day.tz();
 "America/Santiago"
 day.format();
 "2018-08-11T00:00:00-04:00"  // shift day
 day.add(1, 'day').format();
 "2018-08-11T23:00:00-04:00"

Romanior avatar Jul 14 '18 12:07 Romanior

The same issue that @Romanior mentioned is what I brought up here:

  • https://github.com/moment/moment/issues/4743

The America/Santiago timezone causes lots of issues in code, even infinite loops when certain assumptions are made.

CoryDanielson avatar Aug 27 '18 19:08 CoryDanielson

Workaround for m.add(x, 'days'):

function switchZone(m, zone) {
  let arr = [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second()];
  if(zone) {
    return moment.tz(arr, zone);
  }
  return moment(arr);
}

function safeAddDays(m, days) {
   let oldZone = m.tz();
   let utc = switchZone(m, 'UTC');
   utc.add(days, 'days');
   return switchZone(utc, oldZone);
}

mblandfo avatar Jul 25 '19 22:07 mblandfo