I'm storing UTC datetime on the server and requesting data via JSON to display on client. The problem is that the server returns the time by its timezone which is different to a client. How could I get the local dateTime to display on client without hardcoding the offset?
I'm using ASP.NET MVC and storing date and time in SQL Server 2008 database as 'datetime'. DateTime format in database is 2013年03月29日 08:00:00.000.
-
What server-side language are you using? PHP/ASP.NET/something else?Danny Beckett– Danny Beckett2013年03月31日 00:35:04 +00:00Commented Mar 31, 2013 at 0:35
-
have you tried adding 'UTC' to the string as mentioned here: stackoverflow.com/questions/6525538/…proggrock– proggrock2013年03月31日 00:36:35 +00:00Commented Mar 31, 2013 at 0:36
-
I'm using asp.net mvc.agri– agri2013年03月31日 00:49:42 +00:00Commented Mar 31, 2013 at 0:49
-
String comes back from the server as "Use_DateTime":"\/Date(1364482800000-0700)\/" and this is already Server datetime. As I understand adding 'utc' there wouldn't help.agri– agri2013年03月31日 00:59:24 +00:00Commented Mar 31, 2013 at 0:59
2 Answers 2
You don't say how the UTC time is represented. It's common to use a UNIX time value that is seconds since 1970年01月01日T00:00:00Z. If that is what you are using, you can create a date object on the client by multiplying by 1,000 and giving it to the Date constructor:
var unixTimeValue = '1364694508';
var clientDateObject = new Date(unixTimeValue * 1000);
If you are using say .NET, the value may already be in milliseconds so you don't need to multiply by 1,000. You need to check with the source to see what value is passed and what epoch is used if it's a time value.
Javascript date objects are based on a time value that is the same epoch as UNIX, but uses milliseconds. The standard Date methods (getFullYear, getMonth, getDate, etc.) will return values in the local timezone based on system settings. The UTC methods (getUTCFullYear, getUTCMonth, getUTCDate, etc.) return UTC values for the same time.
So if you are passing a time value, use it to create a date object on the client and read the values using standard methods and you have local equivalents of the UTC time value.
If you are passing a datetime string like 2013年03月31日T14:32:22Z, you can convert that to a date object using Date.UTC to convert the string to a time value, then give that to the date constructor:
function dateFromUTCString(s) {
s = s.split(/[-T:Z]/ig);
return new Date(Date.UTC(s[0], --s[1], s[2], s[3], s[4], s[5]));
}
var s = '2013-03-31T14:32:22Z';
alert(dateFromUTCString(s)); // Mon Apr 01 2013 00:32:22 GMT+1000 (EST)
If your input string is a different format, you may need to adjust the split pattern and order of parameters passed to Date.UTC.
Edit
If the string format is 2013年03月29日 08:00:00.000 (assuming UTC), you can use:
function dateFromUTCString(s) {
s = s.split(/[\D]/ig);
return new Date(Date.UTC(s[0], --s[1], s[2], s[3], s[4], s[5], s[6]||0));
}
var s = '2013-03-29 08:00:00.000';
alert(dateFromUTCString(s)); // Fri Mar 29 2013 18:00:00 GMT+1000 (EST)
But be careful of additional spaces. You might want to trim any leading or trailing spaces and ensure there is only one separating the date and time components.
Edit 2
Don't use Date.parse. Until ES5 it was completely implementation dependent. Now it's partially standardised if the string complies with the ISO8601–like format specified by ES5. But that isn't supported by all browsers in use, so not reliable and is otherwise still implementation dependent. The best solution (i.e. one that will work everywhere) is to manually parse the value you are given.
If the format is like: "1364835180000-0700", then you can fairly easily deal with that using a function that subtracts the offset to get UTC time value, the gives that to the date constructor. I'm assuming that -0700 means 7hrs west of Greenwich (javascript timezone offsets have an opposite sense, west of Greenwich is +ve).
Edit 3
Sorry, must have posted the wrong snipped, rushing to a meeting.
// Where s is a time value with offset
function toDate(s) {
// Include factor to convert mins to ms in sign
var sign = s.indexOf('-') > -1? 6e4 : -6e4;
s = s.split(/[\+\-]/);
var l = s[1].length;
// Convert offset in milliseconds
var offset = sign*s[1].substring(l-2,l) + sign*s[1].substring(l-4, l-2)*60;
// Add offset to time value to get UTC and create date object
return new Date(+s[0] + offset);
}
var s = "1364835180000-0700"
alert(toDate(s)); // Tue Apr 02 2013 09:53:00 GMT+1000 (EST)
-
Ok, I'm using SQL Server 2008 and storing date and time as type 'datetime', so it's storing it in 2013年03月29日 08:00:00.000 format.agri– agri2013年03月31日 09:16:38 +00:00Commented Mar 31, 2013 at 9:16
-
Thanks for help.I haven't got it sorted yet but understand it a little bit better. When I looked at my date that comes back from the server in json, I can see the timezone difference by looking at four last digits e.g "\/Date(1364835180000-0700)\/" - 7hrs behind , "\/Date(1364662800000+0000)\/" -utc , "\/Date(1364814000000+0100)\/" - one ahead. Knowing that I can re-calculate the date by adding 7hrs in milliseconds but this date is not quite same to var d=new Date(); var date=Date.parse(d); Is there any obvious way of converting this: (1364662800000+0000) to 1364856878000.agri– agri2013年04月01日 22:57:05 +00:00Commented Apr 1, 2013 at 22:57
-
Your last function seems to be the same as jsonDate = "1364482800000-0700" var d = new Date(parseInt(jsonDate)); or is there difference? jsfiddle.net/karin/Ugjkragri– agri2013年04月02日 09:01:04 +00:00Commented Apr 2, 2013 at 9:01
Return the DateTime as UTC and convert it on the client using .toLocaleString():
@ViewBag.Time = Model.Time.ToUniversalTime().Ticks / TimeSpan.TicksPerMillisecond
<script>
var time = new Date(@ViewBag.Time);
var localTimeString = time.toLocaleString();
alert(localTimeString);
</script>
-
Can you explain me where is the Model.Time coming from? I've tested it but instead Model used DateTime.Now, and got local time, although year was displayed as 3982 instead of 2013. I'm using Repository pattern, so the data is coming through different layers.agri– agri2013年04月01日 12:40:58 +00:00Commented Apr 1, 2013 at 12:40
-
Model.Time is really just whatever you have your Time variable called. You can put the
ViewBag.Time = <whatevertimevariable>.ToUniversalTime().Ticks/TimeSpan.TicksPerMillisecond
either in the View or in the Controller. Probably better to put it in the controller, though.Rob G– Rob G2013年04月01日 23:16:26 +00:00Commented Apr 1, 2013 at 23:16