Change a date string in Javascript preserving the timezone - javascript

I have the following date string: Sat, 23 May 2015 05:49:45 GMT. I need to get this date and add 1 second to it, and end up with Sat, 23 May 2015 05:49:46 GMT. It's important that:
The date string stays the same, with the same timezone. This means that if I do var d = Date.parse('Sat, 23 May 2015 05:49:45 GMT') and then add 1 second to d (easy, d += 1000) and reconvert it back to a string, I end up with Sat May 23 2015 14:49:46 GMT+0800 (AWST) which is not what I want.
(Obviously) It needs to be a "proper" adding of a second, keeping into account the change of hour/date/etc.
What's the best way to go about this? I don't really want to do it purely with String manipulation, because it would be kind of ridiculous.

This means that if I do var d = Date.parse('Sat, 23 May 2015 05:49:45 GMT') and then...
...and then it'll fail on some browser somewhere, because the only date/time format that the JavaScript Date object is required to parse by the specification is completely different from that. If JavaScript parses it in your environment, you have absolutely no guarantee JavaScript will parse it in another environment.
Instead, you need to parse it, which is fairly easy, and then form a new string:
Use a regular expression to capture the day, month, year, and time from the string; you'll need a lookup table giving month name => month number. Glancing at that string, the rex would be something along the lines of /^..., (\d{1,2}) ([^ ]+) (\d{4}) (\d{2}):(\d{2}):(\d{2})/. Then the day number is in capture group 1, the month name in capture group 2, etc.
Create a Date instance via new Date(Date.UTC(year, month, day, hour, minute, second)).
Add a second to it: dt.setUTCSeconds(dt.getUTCSeconds() + 1) (Date will handle the rollover).
Produce a string in the desired format. You'll need a lookup table giving you day number => day name. When getting the parts of the date/time, use the getUTCXyz methods, not the getXyz methods.
(Or you can use a library like MomentJS to do all that for you. [I'm not affiliated with them in any way.])

The Easy Answer
The simplest solution is just to use "Date.toUTCString()" rather than "Date.toString()" method.
Example:
var d = new Date('Sat, 23 May 2015 05:49:45 GMT');
d.setUTCSeconds( d.getUTCSeconds() + 1 );
console.info( d.toUTCString() );
Output:
Sat, 23 May 2015 05:49:46 GMT ( for Chrome, Firefox, Opera, and IE11 )
Sat, 23 May 2015 05:49:46 UTC ( for IE<11 )
In contrast, using toString() will return the date with timezone:
Sat May 23 2015 13:49:46 GMT+0800 (AWST) ( depends on locale )
Additional Details:
In practice, most browsers can parse an RFC2822 date-time which are seen in headers, RSS feeds, etc. The format looks like:
var d = Date('Sat, 23 May 2015 05:49:45 GMT');
Even IE5 can parse this date correctly. The only caveat applies to timezones. It understands named timezones like GMT and EST (USA) but might have trouble with AWST (Australia). Yet, using a time offset, rather than a name, will avoid this problem:
var d = Date('Sat, 23 May 2015 13:49:45 +0800' ); // +8 AWST
Yet, this is not an issue for OP as he is pulling the date from the http header, which will be in GMT ... so no timezones to worry about.
To adjust the date one might be tempted to add milliseconds directly to the date value like d += 1000. Yet, that can have unexpected results. It's safer to use the Date UTC methods so that date calculations use normalized values, e.g.,
d.setUTCSeconds( d.getUTCSeconds() + 1 );
And multiple changes may be made simultaneously like:
d.setUTCHours(
d.getUTCHours() + hours,
d.getUTCMinutes() + minutes,
d.getUTCSeconds() + seconds
);
Reference: MDN Date object
Try it with your browser:
<html>
<body>
<div id="toString"></div>
<div id="toUTCString"></div>
<script type="text/javascript">
var d = new Date( 'Sat, 23 May 2015 05:49:45 GMT' );
d.setUTCSeconds( d.getUTCSeconds() + 1 );
document.getElementById('toString').innerHTML = 'toString = ' + d.toString();
document.getElementById('toUTCString').innerHTML = 'toUTCString = ' + d.toUTCString();
</script>
</body>
</html>

Related

HTML5: hour from "Date()" object in <input type='time'> [duplicate]

I send this date from my controller in java (Spring-MVC) the type in mysql is datetime
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "..") public Date getYy() {
return this.yy;
}
as : [2015-09-30 00:00:00.0]
When i get this dates with ajax as 1443567600000 :
new Date(1443567600000) convert to Tue Sep 29 2015 23:00:00 GMT+0000 (Maroc)
So why i get wrong date off by one hour?
SOLUTION
We resolve it by
d = new Date(value) ;
d.setTime( d.getTime() - new Date().getTimezoneOffset()*60*1000 );
because it was Daylight saving time (DST) or summer time problem. good article
This JS handling of Date is a quite a head-flip.
I'm in the UK... "easy" because we're on GMT (UTC)... except during the summer months, when there's DST (British Summer Time, BST). Clocks go forward in summer and back in winter (stupidly by the way, but that's another issue!) by one hour. One day in March what is 4pm GMT is now called 5pm (BST).
summer month:
If you do new Date( '2017-08-08' ) this will give you (toString) 'Date 2017-08-08T00:00:00.000Z'.
If you do new Date( '2017-08-08 00:00' ), however, this will give you 'Date 2017-08-07T23:00:00.000Z'!
In the second case it appears JS is trying to be "helpful" by assuming that because you stipulated the hour you were specifying BST time. So it adjusts to GMT/UTC. Otherwise it doesn't... though (of course) it still produces a Date object which is specific right down to the milliseconds. Quite a gotcha!
Confirmation: a winter month... when BST is not applied:
new Date( '2018-01-01 00:00' )/ new Date( '2018-01-01' ): both give 'Date 2018-01-01T00:00:00.000Z'
As for adjusting, it appears that to undo the automatic adjustment you just go
jsDate.setTime( jsDate.getTime() + jsDate.getTimezoneOffset() * 60 * 1000 );
... this is a bit like what Youssef has written... except you have to obtain the offset from the specific Date in question... and my experiments seem to prove that you add this, not subtract it.
Really it would be much more helpful if the default string representation of JS Date gave the UTC time followed by the TZ (time zone) offset information, as with some of the ISO date formats: clearly, this information is included.
I think maybe this is a Daylight Saving Time problem. You can check your client's timezone, and your server's timezone. (web server or SQL Server)
We should probably need more data about it, but it could be that nothing is wrong here, it depends how you set and get back your date.
Basically 1443567600000 doesn't contains timezone. It represent Tue Sep 29 2015 23:00:00 from Greenwich. It's a moment in time that, of course, it different from any location that has a different timezone. The same moment, happens at different time (the midnight of GMT+1 is the 11pm of GMT).
You have to store both the time and the timezone in your DB, and possibly send back to JS, otherwise it will be always interpreted differently depends by the local time of the client.
To make an example:
var d = new Date(2015, 8, 30);
console.log(d.toJSON()); // In my case I got "2015-09-29T22:00:00.000Z"
console.log(d.toDateString()); // "Wed Sep 30 2015"
To be more specific
time = new Date("2018-06-01 " + time);
var offset = time.getTimezoneOffset();
offset = Math.abs(offset / 60);
time.setHours(time.getHours() + offset);
in this case time is equal to hours with leading zeros:minutes with leading zeros.
This will add the hours difference to the UTC.
If you pass a string to date it is treated as UTC.

Javascript Date() give wrong date off by one hour

I send this date from my controller in java (Spring-MVC) the type in mysql is datetime
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "..") public Date getYy() {
return this.yy;
}
as : [2015-09-30 00:00:00.0]
When i get this dates with ajax as 1443567600000 :
new Date(1443567600000) convert to Tue Sep 29 2015 23:00:00 GMT+0000 (Maroc)
So why i get wrong date off by one hour?
SOLUTION
We resolve it by
d = new Date(value) ;
d.setTime( d.getTime() - new Date().getTimezoneOffset()*60*1000 );
because it was Daylight saving time (DST) or summer time problem. good article
This JS handling of Date is a quite a head-flip.
I'm in the UK... "easy" because we're on GMT (UTC)... except during the summer months, when there's DST (British Summer Time, BST). Clocks go forward in summer and back in winter (stupidly by the way, but that's another issue!) by one hour. One day in March what is 4pm GMT is now called 5pm (BST).
summer month:
If you do new Date( '2017-08-08' ) this will give you (toString) 'Date 2017-08-08T00:00:00.000Z'.
If you do new Date( '2017-08-08 00:00' ), however, this will give you 'Date 2017-08-07T23:00:00.000Z'!
In the second case it appears JS is trying to be "helpful" by assuming that because you stipulated the hour you were specifying BST time. So it adjusts to GMT/UTC. Otherwise it doesn't... though (of course) it still produces a Date object which is specific right down to the milliseconds. Quite a gotcha!
Confirmation: a winter month... when BST is not applied:
new Date( '2018-01-01 00:00' )/ new Date( '2018-01-01' ): both give 'Date 2018-01-01T00:00:00.000Z'
As for adjusting, it appears that to undo the automatic adjustment you just go
jsDate.setTime( jsDate.getTime() + jsDate.getTimezoneOffset() * 60 * 1000 );
... this is a bit like what Youssef has written... except you have to obtain the offset from the specific Date in question... and my experiments seem to prove that you add this, not subtract it.
Really it would be much more helpful if the default string representation of JS Date gave the UTC time followed by the TZ (time zone) offset information, as with some of the ISO date formats: clearly, this information is included.
I think maybe this is a Daylight Saving Time problem. You can check your client's timezone, and your server's timezone. (web server or SQL Server)
We should probably need more data about it, but it could be that nothing is wrong here, it depends how you set and get back your date.
Basically 1443567600000 doesn't contains timezone. It represent Tue Sep 29 2015 23:00:00 from Greenwich. It's a moment in time that, of course, it different from any location that has a different timezone. The same moment, happens at different time (the midnight of GMT+1 is the 11pm of GMT).
You have to store both the time and the timezone in your DB, and possibly send back to JS, otherwise it will be always interpreted differently depends by the local time of the client.
To make an example:
var d = new Date(2015, 8, 30);
console.log(d.toJSON()); // In my case I got "2015-09-29T22:00:00.000Z"
console.log(d.toDateString()); // "Wed Sep 30 2015"
To be more specific
time = new Date("2018-06-01 " + time);
var offset = time.getTimezoneOffset();
offset = Math.abs(offset / 60);
time.setHours(time.getHours() + offset);
in this case time is equal to hours with leading zeros:minutes with leading zeros.
This will add the hours difference to the UTC.
If you pass a string to date it is treated as UTC.

Javascript New Date Changing Hour Value

I am receiving times in the an AJAX request and am converting them using the new Date() function.
I receive 2013-06-18T12:00:15Z
However, somehow I get the following after new Date():
Tue Jun 18 2013 08:00:15 GMT-0400 (EDT)
Why is it not:
Tue Jun 18 2013 12:00
See the following demo:
http://www.w3schools.com/js/tryit.asp?filename=tryjs_date_convert
This is a time zone problem. You must be in the EDT timezone (GMT-0400). To correctly parse the date you should tell the parser in which timezone your date is correct.
For you parse your date like this :
new Date('2013-06-18 12:00:15 GMT-0400')
"GMT-0400" means GMT time minus 4 hours
Or if you don't wish to reformat your string, you can use the date.getUTC* functions to get the time as you parsed it.
The full list is available at Mozilla's documentation.
I agree with Vaim Caen's answer that this is a timezone issue, but not with parsing - the date is being parsed fine, but into your local timezone, while you're expecting it to be parsed into UTC date.
This answer shows how to convert from your current timezone to UTC - applying this to the TryIt demo gives:
var msec = Date.parse("2013-06-18T12:00:15Z");
// or: var msec = Date.parse("Tue Jun 18 2013 08:00:15 GMT-0400 (EDT)");
var d = new Date(msec);
d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );
document.getElementById("demo").innerHTML = d;
Edit: If you all you're interested in is displaying the date (no further manipulations) then you can use:
d.toUTCString()
which will show the date in GMT (for me it actually shows "GMT" so most likely not of use!)
The alternative is to add a function to the prototype to show the date in whatever format you want and use the date.getUTC* methods.

How do I prevent javascript from converting my dates to GMT?

I have a timestamp given by
timestamp = 2015-02-22T10:00:00.000Z
Why is it converted to GMT when I do this
var dt = new Date(timestamp);
console.log('dt = ' + dt); // prints Sun Feb 22 2015 05:00:00 GMT-0500 (EST)
I don't want it to convert my date to GMT. How do I prevent javascript from converting my dates?
When you try to execute dt = ' + dt, Javascript tries to convert the dt object to a string so it can be added to another string. It does that by calling the dt.toString() method and the format you are seeing is the default string conversion for a date object.
FYI, this default format that looks like this:
Fri Mar 06 2015 19:24:42 GMT-0800 (Pacific Standard Time)
is NOT GMT time. The time value shown is local time. It is showing you that local time shown is -0800 hours from GMT, but the time itself is expressed in local time.
It's not uncommon to want to just truncate off the last part of this and display:
Fri Mar 06 2015 19:24:42
That can be done like this:
console.log('dt = ' + dt.toString().replace(/\sGMT.*$/, ""));
Working demo: http://jsfiddle.net/jfriend00/hg5m0r1r/
If you want something different to show, then you should construct the string representation you want yourself rather than letting the system automatically call .toString(). You can look at the Date object methods available and decide what you want to display. A Date object internally is a number of ms since the epoch time so any string representation is a conversion of some kind. You have to tell it what conversion you want.
You can see a list of the many date methods here.

toDateString() decrements my date

For the following code:
var d = new Date("2013-07-01");
console.log(d.toDateString());
It outputs Sun Jun 30 2013, which is one day less of what was input. What happened to the object? What date is actually stored?
The date is parsed as UTC date, but the toDateString() outputs what that time is in the local timezone.
Try this instead
var d = new Date(2013, 6, 1); //6 instead of 7 because the mont argument is zero-based
console.log(d.toDateString());
What date is actually stored?
2013-07-01 00:00:00 UTC
Parsing a Date from a string can yield different results depending on what browser/runtime you are using. There is a chart here that lists some of the browsers and what they support.
But in general, a string like "2013-07-01" is treated as if it were at midnight in UTC.
If you wanted to parse it in local time, you could use "2013/07/01". But that's a bit strange. You might be tempted to use "07/01/2013", but that might be interpreted as either Jan 7th or July 1st. Any of these are still implementation specific.
If you want a general purpose, "works everywhere" solution, you have a few different options:
Option 1
Don't parse it. Use the constructor that accept integers.
var d = new Date(2013,6,1); // watch out for the zero-based month
console.log(d.toDateString());
// output: "Mon Jul 01 2013"
With this code, the actual UTC time stored is going to vary depending on your own time zone. But since .toDateString() also takes that time into account, then you should be ok.
Option 2
Parse it as UTC, and display it as UTC/GMT:
var d = new Date("2013-07-01");
console.log(d.toUTCString());
// output: "Mon, 01 Jul 2013 00:00:00 GMT"
But this output probably has more than you were looking for, and it may still look different in various browsers.
Option 3
Use the moment.js library, where you can control the formatting exactly however you desire.
var m = moment("2013-07-01", "YYYY-MM-DD"); // explicit input format
console.log(m.format("ddd MMM DD YYYY")); // explicit output format
// output: "Mon Jul 01 2013"
IMHO, this is the best solution. But it does require you use a library.
Option 4
This approach works pretty good and doesn't require 3rd party libraries.
var parts ='2013-07-01'.split('-');
var mydate = new Date(Date.UTC(parts[0],parts[1]-1,parts[2])); //please put attention to the month
You can simply append your timezone before parsing as well.
var d = new Date("2013-07-01" + "T00:00:00.000-05:00");
console.log(d.toDateString());

Categories