I have a WCF REST service that returns date in below format:
/Date(1401993000000+0530)/
The value of this date on the server is
6/6/2014 12:00:00 AM
I want to parse this in my javascript code in UTC value.
I tried manually removing the "+0530" string and parsing it to date but it gives "Invalid Date".
I also tried adding the timezone offset as per this post but it gives incorrect value.
How can I parse this?
This format is commonly referred to as an "ASP.NET JSON Date" - because it first emerged from the JavaScriptSerializer and DataContractJsonSerializer classes used in ASP.NET and other parts of .NET. However, it was heavily criticized, and ultimately deprecated in favor of the standard ISO 8601 format, which is the default in the Json.Net library used in most modern .NET code. You'll still see it in WCF, and in older versions of ASP.NET MVC.
This format has two main variations:
/Date(1401993000000)/ - A timestamp alone
/Date(1401993000000+0530)/ - A timestamp with an offset
You will occasionally see the forward slashes escaped with backslashes, as in \/Date(1401993000000)\/, depending on how it was generated. This should be tolerated by parsers, but should not be depended upon.
In both formats shown, the timestamp portion is intended to represent the number of milliseconds since the Unix Epoch, which is 1970-01-01 00:00:00.000 UTC.
I say "intended", because it is possible in .NET to have a DateTime with DateTimeKind.Unspecified, which can't possibly be mapped back to UTC. In this case, the serializer will act as if it had DateTimeKind.Local. The output will then reflect the value adjusted to UTC in the computer's local time zone, along with the computer's UTC offset for that point in time. Ideally, you should not rely on this behavior, as you will get different results from computers in different time zones.
When an offset is present in the output string, it is in +HHmm/-HHmm format, with positive values falling East of GMT - the same direction as the ISO 8601 standard. However, unlike ISO 8601, the value portion is not adjusted for that offset. It remains UTC-based.
In other words:
/Date(1401993000000)/ = 2014-06-05T18:30:00Z
/Date(1401993000000+0530)/ = 2014-06-05T18:30:00Z + +0530 = 2014-06-06T00:00:00+05:30
Because of this, the offset portion is extraneous when using this value to create a JavaScript Date object - since a Date object wraps a timestamp in UTC, and has no provision for retaining a provided offset.
You can certainly break out the string into its parts and use them yourself,
but instead consider using Moment.js for parsing this string. It understands the format natively, and can give you back an object that retains knowledge of the offset.
var m = moment.parseZone("/Date(1401993000000+0530)/");
m.format() // "2014-06-06T00:00:00+05:30"
If you were looking for a Date object, you can certainly call m.toDate(). The resulting Date object will have the same UTC timestamp, but due to how the Date object works, any local-time functions will only use the offset of the host environment.
In other words, with output of a Date object, the +0530 part of your input becomes useless. You might have well have parsed /Date(1401993000000)/.
You can use Moment JS, one of the better ways to play with datetime in JavaSCript. Lot of functions
https://momentjs.com/timezone/
See the edited message, without momentjs:
var data = [ {"id":1,"start":"/Date(1401993000000+0530)/"} ];
var myDate = new Date(data[0].start.match(/\d+/)[0] * 1);
myDate = new Date(myDate.getTime() + myDate.getTimezoneOffset() * 60 * 1000);
alert(myDate);
Related
I have a string representing the current time: 2015-11-24T19:40:00. How do I parse this string in Javascript to get a Date represented by this string as the LOCAL TIME? Due to some restriction, I cannot use the library moment, but jquery is allowed. I know that someone has asked this question before, but the answer used moment
For example, if I run the script in California, then this string would represent 7PM pacific time, but if I run the script in NY then this string would represent Eastern Time?
I tried the following but Chrome and Firefox give me different results:
var str = "2015-11-24T19:40:00";
var date = new Date(str);
Chrome consumes it as UTC time (Tue Nov 24 2015 11:40:00 GMT-0800 (Pacific Standard Time)),
but Firefox consumes it as my local PACIFIC time (Tue Nov 24 2015 19:40:00 GMT-0800 (Pacific Standard Time))
I tried adding "Z" to str, like this var date = new Date(str+"Z");, then both browsers give me UTC time. Is there any similar letter to "Z" which tells all browsers (at least chrome, Firefox and Safari) to parse the string as local time zone?
Parsing of date strings using the Date constructor or Date.parse (which are essentially the same thing) is strongly recommended against.
If Date is called as a function and passed an ISO 8601 format date string without a timezone (such as 2015-11-24T19:40:00), you may get one of the following results:
Pre ES5 implementaitons may treat it as anything, even NaN (such as IE 8)
ES5 compliant implementations will treat it as UTC timezone
ECMAScript 2015 compliant implementations will treat it as local (which is consistent with ISO 8601)
A Date object has a time value which is UTC, and an offset based on system settings. When you send a Date to output, what you see is usually the result of Date.prototype.toString, which is an implementation dependent, human readable string representing the date and time, usually in a timezone based on system settings.
The best way to parse date strings is to do it manually. If you are assured that the format is consistent and valid, then parsing an ISO format string as a local date is as simple as:
/* #param {string} s - an ISO 8001 format date and time string
** with all components, e.g. 2015-11-24T19:40:00
** #returns {Date} - Date instance from parsing the string. May be NaN.
*/
function parseISOLocal(s) {
var b = s.split(/\D/);
return new Date(b[0], b[1]-1, b[2], b[3], b[4], b[5]);
}
document.write(parseISOLocal('2015-11-24T19:40:00'));
Note that parsing of ISO strings using Date.parse only accepts UTC, it does not accept any other timezone designation (noting the above behaviour if it's missing).
A variation on RobG's terrific answer.
Note that this will require that you run bleeding edge JavaScript as
it relies on the arrow notation and spread operator.
function parseDateISOString(s) {
let ds = s.split(/\D/).map(s => parseInt(s));
ds[1] = ds[1] - 1; // adjust month
return new Date(...ds);
}
Note that this doesn't take into account if the date/time given is in any timezone. It will assume local time. You can change new Date for Date.UTC to assume UTC.
There are technical reasons for why you would write you code like this. For example, here we apply the correct number of arguments, with their corresponding expected type. It's true that the Date constructor will turn strings into numbers but what could be happening is that there's a deoptimization taking place where the optimized code is expecting a number but sees a string and takes a slower path. Not a big deal but I try to write my JavaScript to avoid such things. We also won't be indexing outside the bounds of the array if less than 6 components can be found in the string which is also one of those things you can do in JavaScript but it has subtle deoptimization caveats.
Where Date is called as a constructor with more than one argument, the specified arguments represent local time.
I also have a much faster way than using the string.split() because we already know where the numbers are:
return new Date(Number(date.substring(0, 4)), Number(date.substring(5, 7))-1,
Number(date.substring(8, 10)), Number(date.substring(11, 13)),
Number(date.substring(14, 16)), Number(date.substring(17, 19)));
This will work with and/or without the 'T' and 'Z' strings and still has decent performance. I added the explicit Number conversion (faster and better than parseInt) so this also compiles in TypeScript.
Number
I have a string representing the current time: 2015-11-24T19:40:00. How do I parse this string in Javascript to get a Date represented by this string as the LOCAL TIME? Due to some restriction, I cannot use the library moment, but jquery is allowed. I know that someone has asked this question before, but the answer used moment
For example, if I run the script in California, then this string would represent 7PM pacific time, but if I run the script in NY then this string would represent Eastern Time?
I tried the following but Chrome and Firefox give me different results:
var str = "2015-11-24T19:40:00";
var date = new Date(str);
Chrome consumes it as UTC time (Tue Nov 24 2015 11:40:00 GMT-0800 (Pacific Standard Time)),
but Firefox consumes it as my local PACIFIC time (Tue Nov 24 2015 19:40:00 GMT-0800 (Pacific Standard Time))
I tried adding "Z" to str, like this var date = new Date(str+"Z");, then both browsers give me UTC time. Is there any similar letter to "Z" which tells all browsers (at least chrome, Firefox and Safari) to parse the string as local time zone?
Parsing of date strings using the Date constructor or Date.parse (which are essentially the same thing) is strongly recommended against.
If Date is called as a function and passed an ISO 8601 format date string without a timezone (such as 2015-11-24T19:40:00), you may get one of the following results:
Pre ES5 implementaitons may treat it as anything, even NaN (such as IE 8)
ES5 compliant implementations will treat it as UTC timezone
ECMAScript 2015 compliant implementations will treat it as local (which is consistent with ISO 8601)
A Date object has a time value which is UTC, and an offset based on system settings. When you send a Date to output, what you see is usually the result of Date.prototype.toString, which is an implementation dependent, human readable string representing the date and time, usually in a timezone based on system settings.
The best way to parse date strings is to do it manually. If you are assured that the format is consistent and valid, then parsing an ISO format string as a local date is as simple as:
/* #param {string} s - an ISO 8001 format date and time string
** with all components, e.g. 2015-11-24T19:40:00
** #returns {Date} - Date instance from parsing the string. May be NaN.
*/
function parseISOLocal(s) {
var b = s.split(/\D/);
return new Date(b[0], b[1]-1, b[2], b[3], b[4], b[5]);
}
document.write(parseISOLocal('2015-11-24T19:40:00'));
Note that parsing of ISO strings using Date.parse only accepts UTC, it does not accept any other timezone designation (noting the above behaviour if it's missing).
A variation on RobG's terrific answer.
Note that this will require that you run bleeding edge JavaScript as
it relies on the arrow notation and spread operator.
function parseDateISOString(s) {
let ds = s.split(/\D/).map(s => parseInt(s));
ds[1] = ds[1] - 1; // adjust month
return new Date(...ds);
}
Note that this doesn't take into account if the date/time given is in any timezone. It will assume local time. You can change new Date for Date.UTC to assume UTC.
There are technical reasons for why you would write you code like this. For example, here we apply the correct number of arguments, with their corresponding expected type. It's true that the Date constructor will turn strings into numbers but what could be happening is that there's a deoptimization taking place where the optimized code is expecting a number but sees a string and takes a slower path. Not a big deal but I try to write my JavaScript to avoid such things. We also won't be indexing outside the bounds of the array if less than 6 components can be found in the string which is also one of those things you can do in JavaScript but it has subtle deoptimization caveats.
Where Date is called as a constructor with more than one argument, the specified arguments represent local time.
I also have a much faster way than using the string.split() because we already know where the numbers are:
return new Date(Number(date.substring(0, 4)), Number(date.substring(5, 7))-1,
Number(date.substring(8, 10)), Number(date.substring(11, 13)),
Number(date.substring(14, 16)), Number(date.substring(17, 19)));
This will work with and/or without the 'T' and 'Z' strings and still has decent performance. I added the explicit Number conversion (faster and better than parseInt) so this also compiles in TypeScript.
Number
I'm trying my best to figure out how to persist a datetimeoffset string to the server so that it correctly binds to a DateTimeOffset property.
I've tried using something like this:
moment.utc().format() + ' +' + new Date().getTimezoneOffset() / 60 + ':00';
This was showing as 6/12/2017 22:27 +4:00 and I was sending that to the server as a string but it seems to fail being parsed to a DateTimeOffset object every time.
I'm using Nancy for my web api framework at the moment, but I wonder the same thing for Web API as well.
Currently I'm just sending back the offset and setting the DateTimeOffset property like this:
dto.CommentDate = new DateTimeOffset(DateTime.UtcNow).ToOffset(new TimeSpan(dto.Offset, 0, 0));
Is there a better way to do this? Can I send the whole date instead of just the offset?
A few things:
+04:00 is an offset used in parts of Russia, and a few places in the Middle-East. From the location mentioned on your blog, I think you meant -04:00, which is used for Eastern Daylight Time in the US (among others). (The JavaScript getTimezoneOffset method is inverted with this regard.)
+ ':00' assumes that all time zone offsets are in terms of whole hours. In reality, many are :30 and a few are :45.
In a DateTimeOffset, the DateTime portion is always the local time, not the UTC time. In other words, the offset is already applied.
For example, if the local time is 2017-06-16 12:00:00 in the US Eastern time zone, then we'd represent that as 2017-06-16T12:00:00-04:00 (in ISO 8601 format). The corresponding UTC time would be represented as 2017-06-16T16:00:00Z.
Sending the UTC time plus the the local offset is not allowed in ISO 8601 format. The only format I'm aware of that uses that convention is the older "ASP.NET JSON Date Format", that came out of things like JavaScriptSerializer class in .NET. The corresponding value to the previous example would be /Date(1497628800000-0400)/. As you can see, the timestamp portion is a millisecond-resolution version of Unix Time, which is UTC based. The offset has not been applied, and is thus extraneous. This format considered deprecated now, so please don't do this.
You appear to be using moment.js on the client side. This can easily generate the string you need to send.
// get the current time, as an ISO 8601 string, with whole-second resolution
moment().format() // "2017-06-16T12:00:00-04:00"
// or, with millisecond resolution
moment().format('YYYY-MM-DD[T]HH:mm:ss.SSSZ') // "2017-06-16T12:00:00.000-04:00"
On the server side, just expose your property as a DateTimeOffset. Don't try to construct it yourself.
I have a string representing the current time: 2015-11-24T19:40:00. How do I parse this string in Javascript to get a Date represented by this string as the LOCAL TIME? Due to some restriction, I cannot use the library moment, but jquery is allowed. I know that someone has asked this question before, but the answer used moment
For example, if I run the script in California, then this string would represent 7PM pacific time, but if I run the script in NY then this string would represent Eastern Time?
I tried the following but Chrome and Firefox give me different results:
var str = "2015-11-24T19:40:00";
var date = new Date(str);
Chrome consumes it as UTC time (Tue Nov 24 2015 11:40:00 GMT-0800 (Pacific Standard Time)),
but Firefox consumes it as my local PACIFIC time (Tue Nov 24 2015 19:40:00 GMT-0800 (Pacific Standard Time))
I tried adding "Z" to str, like this var date = new Date(str+"Z");, then both browsers give me UTC time. Is there any similar letter to "Z" which tells all browsers (at least chrome, Firefox and Safari) to parse the string as local time zone?
Parsing of date strings using the Date constructor or Date.parse (which are essentially the same thing) is strongly recommended against.
If Date is called as a function and passed an ISO 8601 format date string without a timezone (such as 2015-11-24T19:40:00), you may get one of the following results:
Pre ES5 implementaitons may treat it as anything, even NaN (such as IE 8)
ES5 compliant implementations will treat it as UTC timezone
ECMAScript 2015 compliant implementations will treat it as local (which is consistent with ISO 8601)
A Date object has a time value which is UTC, and an offset based on system settings. When you send a Date to output, what you see is usually the result of Date.prototype.toString, which is an implementation dependent, human readable string representing the date and time, usually in a timezone based on system settings.
The best way to parse date strings is to do it manually. If you are assured that the format is consistent and valid, then parsing an ISO format string as a local date is as simple as:
/* #param {string} s - an ISO 8001 format date and time string
** with all components, e.g. 2015-11-24T19:40:00
** #returns {Date} - Date instance from parsing the string. May be NaN.
*/
function parseISOLocal(s) {
var b = s.split(/\D/);
return new Date(b[0], b[1]-1, b[2], b[3], b[4], b[5]);
}
document.write(parseISOLocal('2015-11-24T19:40:00'));
Note that parsing of ISO strings using Date.parse only accepts UTC, it does not accept any other timezone designation (noting the above behaviour if it's missing).
A variation on RobG's terrific answer.
Note that this will require that you run bleeding edge JavaScript as
it relies on the arrow notation and spread operator.
function parseDateISOString(s) {
let ds = s.split(/\D/).map(s => parseInt(s));
ds[1] = ds[1] - 1; // adjust month
return new Date(...ds);
}
Note that this doesn't take into account if the date/time given is in any timezone. It will assume local time. You can change new Date for Date.UTC to assume UTC.
There are technical reasons for why you would write you code like this. For example, here we apply the correct number of arguments, with their corresponding expected type. It's true that the Date constructor will turn strings into numbers but what could be happening is that there's a deoptimization taking place where the optimized code is expecting a number but sees a string and takes a slower path. Not a big deal but I try to write my JavaScript to avoid such things. We also won't be indexing outside the bounds of the array if less than 6 components can be found in the string which is also one of those things you can do in JavaScript but it has subtle deoptimization caveats.
Where Date is called as a constructor with more than one argument, the specified arguments represent local time.
I also have a much faster way than using the string.split() because we already know where the numbers are:
return new Date(Number(date.substring(0, 4)), Number(date.substring(5, 7))-1,
Number(date.substring(8, 10)), Number(date.substring(11, 13)),
Number(date.substring(14, 16)), Number(date.substring(17, 19)));
This will work with and/or without the 'T' and 'Z' strings and still has decent performance. I added the explicit Number conversion (faster and better than parseInt) so this also compiles in TypeScript.
Number
Colleague and I have scabbed together a little app that uses a bunch of JS in the browser, and communicates with a Tornado (Python3) server via JSON, the server uses mongodb as a backing store for persistent data. This is a sort of first for both of us.
What we're finding difficult is how to interchange datetime information between the JS and Python. We do believe that we should use UTC times for everything. JSON doesn't have a datetime literal, so we have to encode it somehow. We naively (?) used the JS notion of milliseconds from 1970 and have been sharing big integers back and forth. So the JS code might get the current utc now time with something like:
var newTime = new Date().getTime();
On the Python3/mongo side, we'd like to use real datetime objects, so we convert that with something like:
datetime.datetime.utcfromtimestamp(jsMilliseconds / 1000)
But then when we have to send date back, said Python3 object only has a timestamp() method. And round tripping that doesn't seem to create the same time. So we've been frustrated with this.
What we're looking for is for someone with experience to give us a good set of idioms to use here. Should we be using strings, instead of the ms integers when passing back and forth with JSON? What are the recommended methods to use on both sides to go between that format? Or should we stick with the integers and which methods should we be using then?
There are obviously a lot of requirements to consider when dealing with time. However, in the case you want to maintain a Date/Time to be displayed to user in their time zone and use mongo/python/java/javascript, I've used ISO 8601 date formats and always store UTC (Zulu) time. Also, if you truly want to maintain the actual time that something occured, not only do you need to store the "date/time" you need to also store the "timezone" (for example IANA timezone string) where the event occurred.
For a lifetime a reading, you can search for "date time best practices". This answer has a good start on discussion: Daylight saving time and time zone best practices
Alright, now to the code (all of this can be found readily on the internet if you search for
" parse||output ISO 8601 parsing" (e.g. "python parse ISO 8601 date string"):
JSON - on the wire between JavaScript and Python backend send a complex (can be simple if you have no need to preserve time zone) object with ISO-8601 formatted string and string to store time zone string:
{
"dateTime": "1970-07-10T12:00:00.047Z",
"timeZone": "America/New_York"
}
Java Script
a. read datetime string JavaScript: Which browsers support parsing of ISO-8601 Date String with Date.parse
var d = Date.parse("2011-04-26T13:16:50Z");
b. write datetime string How do I output an ISO 8601 formatted string in JavaScript?
var date = new Date();
date.toISOString(); //"2011-12-19T15:28:46.493Z"
Python
a. read datetime string How do I translate a ISO 8601 datetime string into a Python datetime object?
import dateutil.parser
yourdate = dateutil.parser.parse(datestring)
b. write datetime string Python - Convert date to ISO 8601
import dateutil.parser as parser
date.isoformat()
Mongo - store datetime as native datetime field http://docs.mongodb.org/manual/reference/mongodb-extended-json/#date
a. store datetime string (notice "$date" and that datetime is in ZULU/UTC (denoted by 'Z')):
"dateTime" : { "$date" : "1970-07-10T13:00:00.047Z"}
Reference:
1. IANA TimeZone Databasehttp://en.wikipedia.org/wiki/Tz_database
2. The google calendar API (event resource) can be used as an example for RFC 3339, as well (see start/end): https://developers.google.com/google-apps/calendar/v3/reference/events