Comments (19)
@timrwood - Do we consider a "day" in this context as a calendar day for the target zone? Or is it bound to the runtime's local zone?
I hope it's not just 24 fixed hours. :)
from moment-timezone.
Days should be considered calendar days, so adding one day should result in the same hour but a different offset. This looks like it is a bug.
Adding 24 hours is handled differently than days, and may result in a different hour if the offset is different.
What is really strange about this bug is that the total time added is only one hour, not 23 or 25 hours as I would expect.
I think this is likely a bug somewhere in the addOrSubtractDurationFromMoment function in moment core, but will have to look into it.
from moment-timezone.
That sounds right, but when moment-timezone is present we should be sure we are moving through days in the target zone's calendar.
I would guess that moment is normally using the local zone provided via the Date
class.
I haven't dug in enough to see if moment-timezone overrides the moment default behavior in this regard.
from moment-timezone.
As far as I understand, moment-timezone does not override moment default function, we need to call .tz() function to set timezone, so internally created moment objects have local timezone, that can cause bugs.
Moreover, moment-timezone can not override moment default function that is used internally, because it is a local variable inside anonymous function, so we need some support from moment project.
As for this concrete bug, moment logic is like 'save hours and minutes, add 1 day, set hours and minutes back'.
In combination with updateOffset() on every moment change, it causes the following flow:
- save hours and minutes (hours = 0, minutes = 0, moment = '2012-10-28T00:00:00+01:00')
- set date = date + 1, (moment = '2012-10-29T00:00:00+01:00')
2.1. updateOffset() (moment = '2012-10-28T23:00:00+00:00') - set minutes = saved minutes (moment = '2012-10-28T23:00:00+00:00')
3.1. updateOffset() (moment = '2012-10-28T23:00:00+00:00') - set hours = saved hours (moment = '2012-10-28T00:00:00+00:00')
4.1. updateOffset() (moment = '2012-10-28T01:00:00+01:00')
from moment-timezone.
I think that saving hours and minutes and setting them back is a hacky way.
Maybe we can save tz offset before date change, check if offset changed after days (weeks, months, years) addition (subtraction) and then add offsets difference in this case.
from moment-timezone.
Same shit with startOf(), endOf(), month() functions. I think all manipulation functions that need to change date preserving time works wrong.
from moment-timezone.
This is proabably also effected by moment #831
from moment-timezone.
I have some progress with this issue, the following code seems to fix the issue at least for add/subtract/startOf/endOf day/month.
I overrode 'date' and 'startOf' functions and made time correction based on offsets difference.
'month' function is not overriden because it uses 'date' function inside, and 'endOf' function uses 'startOf' function, so it is not overriden too.
var oldDateFunction = moment.fn.date;
moment.fn.date = function() {
if (arguments.length >= 1) {
var oldOffset = this.zone();
var result = oldDateFunction.apply(this, arguments);
var newOffset = this.zone();
this.add('minutes', newOffset - oldOffset);//restore proper time
return result;
} else {
return oldDateFunction.apply(this, arguments);
}
};
moment.fn.dates = moment.fn.date;
var oldStartOfFunction = moment.fn.startOf;
moment.fn.startOf = function(units) {
if (units === 'day' || units === 'days' || units === 'd') {
var oldOffset = this.zone();
var result = oldStartOfFunction.apply(this, arguments);
var newOffset = this.zone();
this.add('minutes', newOffset - oldOffset);//restore proper time
return result;
} else {
return oldStartOfFunction.apply(this, arguments);
}
}
See http://jsfiddle.net/27ytF/4/ for example and tests.
from moment-timezone.
I haven't really looked at your solution but for anyone else who comes here, you will probably want to add in || units === 'd'
. Or change the whole thing to /^d(ays?)?$/.test(units);
.
from moment-timezone.
Just chiming in with my two cents. Let's make sure we're solving the root problem. As I understand it, the underlying issue is that date()
isn't doing its job here. From @zgmnkv's very nice sequence writeup:
2.
set date = date + 1, (moment = '2012-10-29T00:00:00+01:00')
2.1.
updateOffset() (moment = '2012-10-28T23:00:00+00:00')
That should be '2012-10-29T00:00:00+00:00'
, not '2012-10-28T23:00:00+00:00'
. That's just straight-up off by an hour. The thing about saving the hours and restoring them certainly exacerbates the problem; if I understand its purpose correctly (big if), then it's actually trying to adjust for the ill effects of updateZone
messing with the hour, but here it screws things up by applying itself to the wrong date. I submit that we should just fix date()
, i.e. updateZone
should just get things right. Then the hour/minute stuff would just be a no-op, and we could get rid of it. Otherwise, we'll be fighting battles all over moment's codebase to compensate for the fact that date()
just doesn't work like it's supposed to, like those startOf
/endOf
fixes above.
My proposal is to change updateOffset
so that if we're changing a date or month, just to change the offset without touching the time. Just spitballing, but something like:
moment.updateOffset = function (mom, dontAdjustHours) {
var offset;
if (mom._z) {
offset = mom._z.offset(mom);
if (dontAdjustHours) {
mom._offset = offset;
}
else {
if (Math.abs(offset) < 16) {
offset = offset / 60;
}
mom.zone(offset);
}
}
};
And then pass in that variable from moment where appropriate. I haven't tested any of that, but that's the sort of place the fix should be.
from moment-timezone.
@joshbambrick, you're right, thanks for the correction.
I agree with @icambron, this solution looks good. Btw, shouldn't there be offset = offset * 60;
instead of offset = offset / 60;
? Or maybe we can remove this block because moment.js interprets offset as hours if it is < 16 and > -16.
from moment-timezone.
@zgmnkv I just pasted that from the current code. But I agree it looks wrong and that moment's zone()
handles the < 16 case anyway.
from moment-timezone.
So have you reached a formal conclusion to this? This is quite a big issue, and it would be good to see some changes to the actual source code.
from moment-timezone.
@joshbambrick - I think the next step is a pull request. Since I don't actually use the moment-timezone
project (I'm just here to help a bit by virtue of my involvement with Moment itself), it's not going to be me.
from moment-timezone.
Just for reference (as I have just discovered the same problem) this also happens with the isBefore/isSame/isAfter trio.
from moment-timezone.
I noticed an issue with startOf
and endOf
that is related to this.
Asking for endOf('day')
for the date Sun Mar 10 2013 23:59:59 GMT-0400 (EDT)
gives 22:59:59 of the following day (23 hours later than expected). And asking for startOf('day')
for the same date gives 23:00:00 of the previous day (1 hour earlier than expected).
More detail in this gist: https://gist.github.com/bantic/a0801aa2f5fccb9bb8e0
from moment-timezone.
Not positive, but I believe this is related:
# Trying to get the timestamp for the beginning of 3/9/14, the DST day in Boston
moment().tz("US/Eastern").year(2014).month(2).date(9).hour(0).minute(0).second(0).millisecond(0).format()
# output => "2014-03-08T23:00:00-05:00"
US/Eastern changes from UTC -5 to UTC -4 at 2am on 3/9, but I'd expect this to still give me 2014-03-09T00:00:00-05:00.
from moment-timezone.
I see a fix mentioned here is now in the dev branch... does that mean we can expect this out soon? Any idea when the next release will be?
from moment-timezone.
This is fixed in the 0.1.0
release.
var mom = moment('2012-10-28 00:00:00+01:00').tz('Europe/London');
console.log(mom.format()); // 2012-10-28T00:00:00+01:00
mom.add('days', 1);
console.log(mom.format()); // 2012-10-29T00:00:00+00:00
@eipark, your example is fixed as well.
moment().tz("US/Eastern").year(2014).month(2).date(9).hour(0).minute(0).second(0).millisecond(0).format();
// 2014-03-09T00:00:00-05:00
from moment-timezone.
Related Issues (20)
- Error when using clone() and add() on a date in the America/Santiago timezone, where a daylight saving time change occurs. HOT 1
- moment().valueOf returns a value even though it's invalid HOT 2
- The DST calculation does not take effect. HOT 3
- import moment from 'moment-timezone'; import 'moment/min/locales'; not working HOT 5
- Can not set default timezone HOT 2
- Wrong timezone conversion
- error TS2350: Only a void function can be called with the 'new' keyword. new moment(); HOT 3
- 2023d is out HOT 2
- Some tz.guess() tests are failing in 2024 HOT 1
- Canada/Yukon offset before 1967 May 27 is wrong HOT 1
- How does moment.tz(unixTimestamp,timezone) and moment.tz.guess() work? HOT 1
- How can I use moment-timezone with 10 year data range with Typescript types HOT 1
- Moment Timezone has no data for Europe/Ljubljana
- Kazakhstan will switch to a single time zone, UTC+05:00, on March 1, 2024. HOT 1
- 2024a released HOT 1
- Test failure due to rounding error HOT 2
- Timezone Error in v0.5.45 HOT 1
- Wrong Kazakhstan Timezone in 0.5.45 HOT 1
- Incorrect Timezone Offset for 'Asia/Almaty' HOT 1
- The moment-timezone get the time zone of Kazakhstan Asia/Almaty in January 2024 to the DST. HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from moment-timezone.