How to create dates in another timezone, in browser Javascript - javascript

I have a client side web application where the user must create Dates for timezones other then their own, and I'm not sure of the best way to do this.
Using Moment Timezone, I know how I can change a time into another timezone. That is, convert Nov 18 2013 11:00:00 GMT-0500 to Nov 19 2013 03:00:00 GMT+1100. These still represent the same absolute time, but just with a different 'view'.
What I need to do is convert, respecting daylight savings, Nov 18 2013 11:00:00 America/Toronto" to Nov 18 2013 11:00:00 Australia/Sydney (which are different absolute times).
So far the only way I can come up with is to create a Date, serialize it to string, and then parse it with Moment Timezone, something like:
localEvent = new Date(2015, 03, 10, 18, 30)
eventStr = localEvent.toString().split('GMT')[0]
# eventStr = 'Fri Apr 10 2015 18:30:00'
event = moment.tz(eventStr, 'Australia/Sydney')
So now this code will create the exact same point in time regardless of which timezone the browser is operating in.
But this feels very hacky, is there a better way to do this?

Yes, you can do that better:
var zone = moment().tz('Australia/Sydney');
var c = moment(new Date(2015, 03, 10, 18, 30));
c.utcOffset(zone.utcOffset(), true);
// ^--- this flag keeps the same time
// while shifts a timezone
console.log(c.format());
JSFiddle: http://jsfiddle.net/8m6rdzqj/
How I found it: I just went through the moment and moment-timezone source: https://github.com/moment/moment-timezone/blob/master/moment-timezone.js#L347

Related

Wrong date with angular material's date picker

I use the datepicker to pick a date and send it to the server.
When I log the JS value I get the correct result:
Tue Mar 22 2016 00:00:00 GMT+0100 (Mitteleuropäische Zeit)
but in the ajax request it is
2016-03-21T23:00:00.000Z
I don't modify the values, just giving the object to angulars http function.
Does Angular need some configuration to handle it?
You can try the following piece of code
dateObj.setMinutes((dateObj.getMinutes() + dateObj.getTimezoneOffset()));
No need of localization, use this code just before doing any service call. It will pass you the exact date what you selected in the datepicker.
It will work in all timezone (+) and (-),
Example: 2016-03-21 00:00:00 GMT+0100, the above said code covert it as 2016-03-21 01:00:00 GMT+0000. While on Service it converts it as 2016-03-21 00:00:00.
I think it will solve your problem.
Those two strings represent the same time. One is in UTC, i.e. GMT +0, which you can see from the Z ending. The other is in a different timezone, specifically GMT +1 hour.
If you had javascript date objects for both strings, and turned them into integers, i.e. seconds passed since Jan 1, 1970, UTC, you'd find them identical. They represent the same instant but in two different geographic locations.
var d1 = new Date('Tue Mar 22 2016 00:00:00 GMT+0100');
var d2 = new Date('2016-03-21T23:00:00.000Z');
Number(d1); // 1458601200000
Number(d2); // 1458601200000
Generally this is a good thing. Dealing in timezones gets very confusing. I find it best for a server to always deal in UTC.
https://github.com/angular/material/pull/9410
Check out the 1.1.1+ version. This will solve your issue.
<md-datepicker ng-model="date" ng-model-options="{ timezone: 'utc' }"></md-datepicker>
If suppose am selecting a date like Tue Aug 06 2019 00:00:00 GMT+0530 (India Standard Time), am getting 2019-08-05T18:30:00.000Z. ( which in my case previous date with respect to the selected date)
I made use of toLocalDateString() to do the job.
// this.date = 2019-08-05T18:30:00.000Z
const converted = new Date(this.date).toLocaleDateString();
console.log(converted); // 8/6/2019 (MM/DD/YYYY) format

Difference between setUTCminutes versus setMinutes

Is there any difference between the JavaScript date methods:
setUTCminutes()
versus
setMinutes()
Will using setMinutes() revert the time zone back to something other than UTC?
I'm contemplating whether to set the UTC time with a date string:
var dUTC = new Date('March 20, 2016 20:45:00 UTC');
or set the date, then set the hour, etc with UTC methods:
var d = new Date(2016,3,20);
d.setUTCHours(20);
d.setUTCminutes(45);
But, I'm concerned that the second method might not be accurate in some situations. I don't want to end up with the wrong UTC date. My Add-on could be used all over the world.
Is there any difference between the JavaScript date methods:
setUTCminutes() versus
setMinutes()
Yes. Set UTCMinutes will adjust the internal timevalue (which is UTC) based on the new UTC minutes value.
setMinutes does the same thing but will allow for the internal timezone, so the change in time might be different (since many time zones are not full hours).
e.g. for a timezone of UTC+0030, if the local time is 01:00 then setting the UTC minutes to 30 does nothing (since it's currently UTC 00:30) but setting the local minutes to 30 will set the UTC minutes to 00:00
Also, if the new minutes causes the date to across a daylight saving boundary, the new time minus the old time in UTC and local might be different.
Will using setMinutes() revert the time zone back to something other than UTC?
No. Date objects do not have a timezone, host systems do. Date objects use a UTC time value, then use the timezone of the host is used in calculations, it isn't a property of the Date itself (hence the method getTimezoneOffset).
I'm contemplating whether to set the UTC time with a date string:
var dUTC = new Date('March 20, 2016 20:45:00 UTC');
NO! Do not do that. Parsing strings with the Date constructor is strongly recommenced against (just search on the number of questions here about parsing). That date format is not one supported by ECMA-262 so parsing is entirely implementation dependent. The time zone might be reconized or not, or you might get an invalid date.
or set the date, then set the hour, etc with UTC methods:
var d = new Date(2016,20,3);
d.setUTCHours(20);
d.setUTCminutes(45);
But, I'm concerned that the second method might not be accurate in
some situations.
The values passed to the Date constructor do not seem correct, the values are year, month, day. Perhaps you meant:
new Date(2016, 3, 20) // 20 April, 2016
When creating the date in the above, the host timezone will affect the values used to create the UTC time value. Using UTC methods to then set the time may well cause unexpected results, so don't to that.
If you want something that works everywhere, always use UTC then only convert to "local" for output. So if you want to create a date and time based on UTC:
var d = new Date(Date.UTC(2016, 3, 20, 20, 45);
will create a date for 2016-04-20T20:45:00Z
A Date instance is always, at heart, a UTC timestamp. The non-UTC APIs, like .toString(), .getHour(), .getMinute(), etc, all apply a translation based on the time zone of the environment in which the code runs. The non-UTC setters do the same thing.
So, in any locale, when you call new Date(), you get a Date instance that acts like it's appropriate for your local time zone, but internally it's a UTC timestamp.
If you want to explicitly make a Date instance from UTC parameters, you can use Date.UTC() to create a timestamp to pass to the Date constructor:
var utc = new Date(Date.UTC(2016, 1, 29, 19, 11, 45));
That makes a Date instance that would be the same as a Date instance constructed by a computer in London (it's not BST now) with:
var london = new Date(2016, 1, 29, 19, 11, 45);
because London time (when it's not summer) is the same as UTC time.
MDN:
The setMinutes() method sets the minutes for a specified date according to local time.
The setUTCMinutes() method sets the minutes for a specified date according to universal time.
If the local time zone does not have hourly offset (eg. India GMT+5:30), then the result will be different.
new Date(new Date('March 20, 2016 20:45:00 UTC')).toString()
"Mon Mar 21 2016 02:15:00 GMT+0530 (India Standard Time)"
new Date(new Date('March 20, 2016 20:45:00 UTC')).toUTCString()
"Sun, 20 Mar 2016 20:45:00 GMT"
new Date(new Date('March 20, 2016 20:45:00 UTC').setMinutes(0, 0, 0)).toString()
"Mon Mar 21 2016 02:00:00 GMT+0530 (India Standard Time)"
new Date(new Date('March 20, 2016 20:45:00 UTC').setMinutes(0, 0, 0)).toUTCString()
"Sun, 20 Mar 2016 20:30:00 GMT"
new Date(new Date('March 20, 2016 20:45:00 UTC').setUTCMinutes(0, 0, 0)).toString()
"Mon Mar 21 2016 01:30:00 GMT+0530 (India Standard Time)"
new Date(new Date('March 20, 2016 20:45:00 UTC').setUTCMinutes(0, 0, 0)).toUTCString()
"Sun, 20 Mar 2016 20:00:00 GMT"

Explain javascripts Date() functions

Why is it when I have
var dt = new Date(2015, 6, 1);
dt.toUTCString()
My output is Tue, 30 Jun 2015 23:00:00 GMT
And
var dt = new Date(2015, 6, 2);
dt.toUTCString()
Wed, 01 Jul 2015 23:00:00 GMT
I'm clearly missing something here, I want to be able to loop through each days of the month and get a Date() for that day
I don't understand why if the day is 1, it says the date is the 30th
Javascript dates are always generated with local time zone. Using toUTCString converts the time in the Date object to UTC time, and apparently in your case that means -1 hours. If you want to initialize a Date object with UTC time, use:
var dt = new Date(Date.UTC(2015, 6, 1));
The toUTCString() method converts a Date object to a string, according to universal time.
The Universal Coordinated Time (UTC) is the time set by the World Time Standard.
Note: UTC time is the same as GMT time.
Try to change dt.toUTCString() in another function.
There are a lot of hour on the planet,for example in America is the 5 o' Clock,in Japan is 10 o' Clock etc... the UTC is a time zone,try to change this.

Moment.js issue adding days with Daylight Savings Time

In Moment.js I have the next problem:
1.I create a moment date:
var m = moment(new Date(2014, 9, 18, 0, 0, 0));
2.If I call toString function:
m.toString() //"Sat Oct 18 2014 00:00:00 GMT-0300"
3.Now, I add one day I have the next output:
m.add("days",1).toString() //"Sat Oct 18 2014 00:00:00 GMT-0300"
What I get 18 again? Momentjs should change the date.
EDIT: Issue in Chrome 32.0.1700.76 m
EDIT2: MomentJs version 2.5.1
EDIT3: Timezone UTC-3
I have looked at you code and at first I did not get the same results. However when I changed the timezone to Brazil (GMT-03:00) - Sao Paulo I got the same result. This is clearly a bug and has now been traced to V8 and reported.
Plunker
var m = moment(new Date(2014, 9, 18, 0, 0, 0));
console.log(m.toString());
console.log(m.add("days",1).toString());
Sat Oct 18 2014 00:00:00 GMT-0300 script.js:4
Sat Oct 18 2014 00:00:00 GMT-0300 script.js:5
I have submitted a bug: https://github.com/moment/moment/issues/1440
Update
Moment.js is not responsible for this bug. It has been tracked to a bug in V8 (the javascript engine used by both Chrome and Node). I have filed a bug with V8 that you can follow here: https://code.google.com/p/v8/issues/detail?id=3116
Here is the work that Isaac Cambron did to track it down.
OK, reproduced now in both Ubuntu and OSX (I was using a different Brazilian city in my tests before). I'm using Node, not Chrome, but for our purposes V8 is V8.
moment([2014, 9, 18]).add(1, 'd').format(); //=> '2014-10-18T00:00:00-03:00'
The problem is that Moment essentially does this:
var d = new Date(2014, 9, 18);
d.setDate(19);
d.toString(); // => Sat Oct 18 2014 23:00:00 GMT-0300 (BRT)
//wtf?
Then it sets the hours to zero. Since V8 weirdly sets the time to late on Oct 18 even though we specifically asked it to set it to Oct 19, the answer comes out wrong. This is all especially weird because the DST transition here is a jump forward, meaning if anything it should end up 1:00, not 23:00 the previous day.
In fact, it even does this:
new Date("October 18, 2014"); //=> Sat Oct 18 2014 00:00:00 GMT-0300 (BRT)
new Date("October 19, 2014"); //=> Sat Oct 18 2014 23:00:00 GMT-0300 (BRT)
According to this jsFiddle, what you're doing /should/ be working. What browser are you testing in?
http://jsfiddle.net/mori57/Nq3KD/
var m = moment(new Date(2014, 9, 18, 0, 0, 0));
console.log(m.toString()); // Firebug output: Sat Oct 18 2014 00:00:00 GMT-0400
console.log(m.add("days",1).toString()); // output: Sun Oct 19 2014 00:00:00 GMT-0400
Simply you can use the below code to get next date in moment.js
var date='2014/09/18';
var nextDate = moment(date, 'YYYY/MM/DD').add('days', 1).format('YYYY/MM/DD');
console.log(nextDate); // 2014/09/19
For more details , look at below link
momentjs docs
This is a rather old post but I got here via Google with the same issue. What I ended up using was the following code, maybe this is helpful for someone else:
var then = moment("23.07.2014", "DD.MM.YY");
var before = moment.unix(then.unix()-86400); // 86400 seconds/day
var after = moment.unix(then.unix()+86400);
General remark to avoid issues like this (as you can see, they do happen, and are sometimes happening due to a browser bug): if you represent a day using Date object, you can just have a convention to pass noon (12h00) instead of midnight (00h00) to the Date constructor, and then in the function that prepares date for display, cut it off.
The bugs in browsers, and issues due to DST usually shift the time by one hour (time goes back from 00h00 to 23h00 the previous day). If you just use midday, it should not happen (in case of similar bugs, time will go back from 12h00 to 11h00 for instance, but the day will not change).
(Of course you need to remember that the date is noon when you pass it around, sometimes it might not be good)
For instance, have a look at this bug in YUI library which we were using in on of our company apps:
https://github.com/yui/yui2/pull/15
This happened only in Firefox, only on Windows, only in particular timezone, and only in particular month. But it did happen.
You should pass the number first and then the "days"
var m = moment(new Date(2014, 9, 18, 0, 0, 0));
console.log(m.toString());
console.log(m.add(1, "days").toString());
Tested in Chrome Version 50.0.2661.37 beta-m (64-bit)

DST problem storing date in Javascript Date object

I have this simple Javascript code
var d = new Date(2011, 9, 8);
alert(d); // Show: Fri Oct 7 23:00:00 UTC-0400 2011
Important: My Time Zone is "Santiago de Chile", and I set computer clock to: 2-Oct-2011.
Alert show that Day is 7!!... why? How I can get it right? (Problem is only in this day)
According to this page DST change in Chile is always at the second full weekend of October and starts at midnight (lets disregard the extended DST of this year, as it's very likely your computer doesn't know about it).
That means that, as is also shown using the script I linked to earlier, at your timezone 8 Oct 2011 midnight can't be represented in UTC-0300, so it automatically switches to UTC-0400 to represent the same time.
I can reproduce your issue in my timezone (Amsterdam, UTC+1/2h) by asking for Sun 27 March 2011, 2:00 AM (with current timezone CEST=UTC+0200) (at which time summer time (CEST) starts and the clock is adjusted from UTC+0100 to UTC+0200) (remember this is exactly the opposite on the northern hemisphere))
new Date(2011, 2, 27, 2, 0, 0, 0);
which effectively can't be represented in UTC+0200, so the system chooses UTC+0100 and outputs
Sun Mar 27 2011 01:00:00 GMT+0100 (CET)
So, it's the same time in Unix time, only represented differently in your local timezone.
And yes, I know 8 October is a Saturday and DST change starts at Sunday, midnight, but this is the closest I can get.
Update: I can now reproduce your issue by setting the timezone of a WinXP machine to Santiago and let the OS automatically adjust for DST and alerting new Date(2011, 9, 9) (which is a Sunday and is shown as a Saturday; there must be something strange with your settings). Of course you can't control these settings on the client.
To work around this issue, I have to know what you exactly need: if you merely want some date/time display that doesn't take timezone and DST into account, just use UTC, like:
var d = new Date(Date.UTC(2011, 9, 9));
alert(d.toUTCString()); // Shows: Sun, 9 Oct 2011 00:00:00 UTC
To show/calculate with the individual parts of the Date object, use the corresponding UTC methods.

Categories