I'm using FormatJS library along with Handlebars to display a list of events that occured in the past. I'm calling for an endpoint on my server's REST API which returns me the list of events in Json, with datetimes to display for each event. ATM I'm saving datetimes in the DB using GMT time zone.
So when I'm getting my Json, I'm handling datetimes like this :
{{formatRelative commentDate}}
My issue is, since the datetimes are stocked in GMT, they display also like that. For example, since I'm on a GMT+2 timezone, as soon as a new event is created and shows up on the list, I see it "happened 2 hours ago" while it should be "a few seconds ago".
So, is there a way I can handle this ? Am I making a mistake in saving datetimes in GMT in my DB, and if so, how would you handle datetimes coming from different timezones and displaying them to people in other timezones ?
Of course I could customize the formatRelative helper to play with getTimezoneOffset and get the wanted result, but I wanted to know if there is something better to do.
Thanks a lot ahead !
The key to understanding your question is what you wrote in the comments:
Getting the Json, containing datetimes in the format 2016-02-28 10:15:53 - that's UTC time
You should ensure the value in JSON is in full ISO8601 format, including the appropriate offset or Z character to indicate UTC: 2016-02-28T10:15:53Z
Without the offset, most implementations will consider the value to be represented in local time, which explains your results.
Thus, the problem is with your server-side code, not your JavaScript code. There may be a client-side workaround you could apply when the date string is parsed from JSON, but really the best solution would be to qualify it at the server.
Related
I'm about to go insane dealing with datetime issues and the web.
I have a web server hosted in the Central Time Zone. When clients in the Eastern Time Zone try and schedule an item for a given day using my app, they pass in the value of (for example) 3/14/2015. When we pass the code back to our model, which is sent to the web api, we persist is using something like the code below.
moment.utc($("#mydatepicker").val).hour(0).minute(0).second(0)).toISOString();
This results in a string like the following:
2015-03-14T04:00:00.000Z
When the item is converted back on the server in web api, it converts to
3/13/2015 11:00:00 PM
Logic then strips off time and you can see what happens from here. Since I stripped off the time, it is now the day prior and that is the value persisted to the database.
I need to know some way to send a value from moment, into the web api preferrably as a ZonedDateTime in the client's time zone. I can then convert it to UTC for persistance in the DB.
I've seen things about using NodaTime.Serialization.JsonNet, but I am unclear on how to to use it with Moment and pass it back and forth across web api/ajax.
I need to know some way to send a value from moment, into the web api preferrably as a ZonedDateTime in the client's time zone. I can then convert it to UTC for persistance in the DB.
If that's what you want, then:
In your moment.js code, use .format() instead of .toISOString(), which will still give you an ISO8601 string, but will include the local offset instead of setting it to UTC.
In your ASP.Net code, define your values as a DateTimeOffset (or a noda OffsetDateTime) rather than a DateTime.
However, I don't think that's really what you want. When it comes to dates and times, context is super important. Here, you said you were picking a date from a date picker. When you do that - what time is being chosen by the user? In most cases, they aren't choosing a time - they're just picking a date. But since the JavaScript Date object is really a "date + time" object, it assigns midnight as a default time. Moment is no better in this regard.
Really, converting to UTC doesn't make logical sense when you are just talking about a calendar date. The string value you probably should be sending across the wire should just be a whole date, as in "2015-03-14". My guess is that is what you are starting with anyway. If not, then do moment.utc(yourvalue).format("YYYY-MM-DD") to get it. (Using UTC here is just a way to avoid local time zone issues, like midnight not existing in Brazil on the spring-forward day.)
This corresponds to the NodaTime LocalDate type in your .NET code. If you weren't using Noda Time, you would define the type as a DateTime and just ignore the time portion. In your database, if there's a date-only type available, then use it. For example, SQL Server has a date type.
I'd also encourage you to watch my Pluralsight course, Date and Time Fundamentals - which covers many of these issues.
Regarding using NodaTime.Serialization.JsonNet in WebAPI (so you can use LocalDate directly), in your WebApiConfig.cs file, wire it up like so:
config.Formatters.JsonFormatter.SerializerSettings
.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
Then it should just work.
I would start by sending all dates and times to the server as UTC times. If you store UTC times only then you should be able to show the correct time that something is scheduled on the client side.
When you create your moment on the client side, do you run it out .toDate() first before sending it to the server side? What code are you running on the server side? Is it a .Net WebApi?
I am having some troubles dealing with the SharePoint date system, and I was hoping to find some advice here. The problem I am facing is that every time I use JS to save a new item to my SharePoint list, the date that I pass (simply yyyy-mm-dd, no time included) is saved as a day earlier than I intended. I am almost certain I know why this is- the timezones are different. While I am at -4, the server is at +1. I am not familiar enough with how SharePoint receives and stores dates to know how I should proceed to get the dates to work properly. Any suggestions would be appreciated.
SharePoint datehandling 101 is that it always store the dates in UTC, that is +-0. When using the gui SharePoint automatically translates the time to your local time. Hence, the date and time you get is the UTC version and when saving datetimes through an API you must ensure if the API is localized or not, if it isn't then store the datetime as UTC.
I have an ajax call, which returns datetime. Javascript displays it using client timezone. I not need in any client timezone, I want to show datetime the same as server return. Is it possible?
I get date via:
var d = eval('new' + date.replace(/\//g, ' '));
First off, there's no reason to use eval here (or almost anywhere), and generally lots of reasons not to.
JavaScript has only "local" time (the timezone of the client) and UTC (universal coordinated time, effectively the same as GMT). So your best bet normally is to have the server send you the time in UTC. But in your case, since you want to display the date in the server's timezone, it doesn't really matter whether JavaScript thinks the date is in local time or server time, and it's fine to send it in the server's timezone.
Note that when parsing date strings, JavaScript only recently (as of ECMAScript5) got a standard format for date strings, which is a simplified version of ISO-8601. Details here. Note that some older browsers will not yet support that format.
It's impossible to offer much more guidance without an example of what you're trying to parse.
Diodeus' suggestion also seems to me to make a lot of sense: If you want the date to be displayed in the server's timezone and format, just display the string you're given without interpreting it (again, subject to what the string looks like; I can't immediately come up with a reasonable format that would work with your posted code).
What is the best approach for dealing with DST values when your web service accepts requests from different timezones than that of your server?
My webservice accepts date strings using the ISO8601 standard (2012-02-21T05:00:00.000-05:00)
I want to account for DST but don't want the overhead of maintaining or connecting to a database to get the DST for each request which comes in from a different timezone to my server.
One approach im considering is using the servers default DST settings and then for each request that comes in convert it to the same timezone as my server is in. Then when the processing is done , convert the string back to the timezone of the client and return. The conversion of the response data could be done on the server or the client.
Any suggestions?
You could also take a look at the XDate project for handling date objects in Javascript. It's quite similar to JodaTime (in Java). Very easy to use and semantic.
XDate project
Here's what I would do. Before you submit your data/time, parse the strings into a JavaScript Date object. Then call getTime() and submit that value. getTime() returns the number of milliseconds since the UTC epoch, so in effect, it normalizes your times. Then when you return data to the user, pass in your UTC millisecond value to the constructor of a Date object and display the time as you would. By default, it'll display in the user's timezone.
I need to write a web application that show events of people in different locale. I almost finished it, but there're 2 problems with date:
using date javascript object, the date depends on user computer settings and it's not reliable
if there's an event in a place with dfferent timezone respect user current position, i have to print it inside (). Is it possible in javascript to build a date object with a given timezone and daylight settings?
I also find some workaround, such as jsdate and date webservices, but they don't overcome the problem of having a javascript object with the correct timezone and daylight settings (for date operation such as adding days and so on).
A couple of things to keep in mind.
Store all event datetimes in UTC time
Yes, there is no getting around this.
Find out all the timezones...
...of all the users in the system. You can use the following detection script: http://site.pageloom.com/automatic-timezone-detection-with-javascript. It will hand you a timezone key such as for example "America/Phoenix".
In your case you need to store the timezone together with the event, since a user may switch timezone - but the event will always have happened in a specific one. (argh)
Choose your display mechanism
If you want to localize your event dates with Javascript, there is a nifty library for that too (which can use the keys supplied with the previous script). Here: https://github.com/mde/timezone-js.
with that library you can for example do this:
var dt = new timezoneJS.Date(UTC_TIMESTAMP, 'America/New_York');
or
var dt = new timezoneJS.Date(2006, 9, 29, 1, 59, 'America/Los_Angeles');
where UTC_TIMESTAMP for example could be 1193855400000. And America/New_Yorkis the timezone you have detected when the event took place.
The dt object that you get from this will behave as a normal JavaScript Date object. But will automatically "correct" itself to the timezone you have specified (including DST).
If you want to, you can do all the corrections in the backend - before you serve the page. Since I don't know what programming language you are using there, I cannot give you any immediate tips. But basically it follows the same logic, if you know the timezone, and the UTC datetime -> you can localize the datetime. All programming languages have libraries for that.
You're missing the point of a Date object. It represents a particular point in time. As I speak, it is 1308150623182 all over the world. Timezone only comes into play when you want to display the time to the user. An operation like "adding a day" does not involve the time zone at all.
One possibility might be to use UTC date and time for everything. That way, there is nothing to convert.
Another is to have your server provide the time and date. Then you don't have to depend on the user to have it set correctly, and you don't have to worry about where your user's timezone is.
Use getUTCDate(), getUTCHours(), ... instead of getDate(), getHours(),...
getTimetoneOffset() could be useful, too.