6

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.

Dale K
28.1k15 gold badges59 silver badges85 bronze badges
asked Mar 31, 2013 at 0:33
4
  • What server-side language are you using? PHP/ASP.NET/something else? Commented Mar 31, 2013 at 0:35
  • have you tried adding 'UTC' to the string as mentioned here: stackoverflow.com/questions/6525538/… Commented Mar 31, 2013 at 0:36
  • I'm using asp.net mvc. Commented 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. Commented Mar 31, 2013 at 0:59

2 Answers 2

6

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)
answered Mar 31, 2013 at 2:02
3
  • 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. Commented 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. Commented 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/Ugjkr Commented Apr 2, 2013 at 9:01
2

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>
answered Mar 31, 2013 at 0:59
2
  • 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. Commented 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. Commented Apr 1, 2013 at 23:16

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.