I just realized that using Javascript's Date object to get the date may return different results depending on the user's browser/computer. Is this the case or does Javascript somehow always returns the actual time, regardless of the user's computer's settings?
Yes, it returns Date as per Users System date:
The Date object enables the JavaScript developer to create a Date
object initialized to a specific time and date, or to create a date
object that reflects the current system time on the computer on which
the browser is running. There are two important things to note when
working with the JavaScript Date object. Firstly, when reading the
date and time of the user's computer you are completely at the mercy
of the user's ability to set and maintain the correct day and time on
their computer. Secondly, whilst you can read the system date and time
set on the user's computer, and change those settings within your Date
object instance, you cannot change the computer's system date and
time. No matter what methods you call or properties you change on your
Date object, the user's system date and time remain unaltered.
http://www.techotopia.com/index.php/JavaScript_Date_Object
Yes. Javascript (generally) runs on the Client side. Anything it does will likely be relative to the clients machine. In this case, the system clock (not the browser AFAIK)
Yes it is entirely dependent on the user's local system time.
If you want to work with the server time, you can always populate the date object with some server side code that prints the current server time.
Different browser implementations should support standard Date object requirements, but some have bugs and some have taken the capabilities further than others. Current time taken from the computer's system time is of course out of your control. Take a look at moments.js. It's a nice little library that deals with such intricacies that you do have control over.
A 5.5kb javascript date library for parsing, validating, manipulating,
and formatting dates.
Related
This might be a very vague question but please bear with me.
I am working on an application that requires me to perform a system time check on clients machine. The issue I am trying to address is, when clients travel across timezones and change their system time instead of changing the timezone it creates problems during the oauth negotiation. How should I go about addressing this problem in such a way that this issue can be self-detected when a client tries to login to the app rather than having to manually detect this kind of issue?
You can call toUtc() on a new DateTime.now() to convert it to UTC. It shouldn't be affected by time zones if it's in UTC, and the string representation will look like "2013-10-18 08:52:16.861Z" (the Z at the end means UTC).
You should be able to use a DateTime in UTC for OAuth negotiation. If not, please share more details; it's probably a bug in either Dart or your OAuth client.
It sounds like your timezones are pretty important so you shouldn't trust JavaScript system time with a 10 foot stick.
If I were you I would use PHP to geo-locate them and apply the timezone based on their location.
You will want to check out Get PHP Timezone Name from Latitude and Longitude?
I'm searching for a way to get client's timezone offset in ExpressJS (with req object, for example, would be really great).
If you control the client, you can do this with client-side JavaScript.
If you don't (e.g. you're building a server-side component like an API), then you can't pull it out of the HTTP request (unless you're using sessions, but even that's not necessarily reliable).
On the upside, if it's only server-side, you shouldn't worry about it either: set all your date objects as UTC or a Unix timestamp and leave it to the client developer to handle timezones.
As others have mentioned, getting the client-side browser/OS timezone offset is not available via HTTP, so you need to send this data from the client side.
In my case I have an app that requires login...so I can store a user's preferences. The default is to use browser timezone, but the user can also configure a specific timezone to use all the time instead which is stored in their user profile (e.g. America/Dallas or Europe/Amsterdam).
I don't trust browser time to be correct. The user may have also screwed up their OS timezone setting...so timezone offset may also not be correct. However most modern OSes set timezone automatically based on Geo-IP implied location...so for many users the convenience of being able to travel around the world and login to the app and see date/time in whatever local timezone they happen to be in is worth the effort for the user experience. Users that always want to see a specific timezone can configure that and we will use that preference instead.
The way I do this is the following... on the login form add a hidden field and set the value with javascript. When the user logs in, store this timezone offset in the session. If the user hasn't set a preferred timezone, then we use this offset when rendering date/time. This means that if you have long sessions and a user can travel around between countries...they will still show the old timezone offset until the next logout/login. You can of course get this data more frequently or even on every request if you want...but for my purposes getting this on login is enough. My sessions are expired on IP address change anyway...so yeah. Of course if their session crosses a daylight savings switch then the offset won't be accurate until the next login (assuming their OS/browser TZ is correct in the first place).
Client Side
<input type="hidden" name="tzOffset" id="tzOffset">
<!-- ... -->
<script>
var tzOffset = new Date().getTimezoneOffset(),
tzInput = document.getElementById('tzOffset');
tzInput.value = tzOffset*(-1);
</script>
Note that I multiple it by -1 because I am going to use moment.js for formatting on the express end and the offset is backwards (utc offset from local vs local offset from utc). You could also do this on the server end. You should probably validate this number as well before using it...just minimal example code here.
Server Side
Then on the server side (express) if there is a successful login, I stick that tzOffset value in the session.
Then when formatting dates in express with moment-timezone I can do something like the following. This function is a "formatter" which I can expose to pug/views and then format any random date object with the right timezone/formats for the user.
function formatDateTimeForUser (date) {
var userTZ, // user specified TZ like Europe/Berlin
userTZoffset, // tzOffset we got from login form
userDateFormat, // user specified date format (or default)
userTimeFormat; // user specified time format (or default)
if (userTZ)
return moment(date).tz(userTZ).format(userDateFormat+' '+userTimeFormat+' zz');
else
return moment(date).utcOffset(userTZoffset).format(userDateFormat+' '+userTimeFormat+' ZZ');
}
The ZZ format is for showing timezone in numeric offset format (relevant when we use a fixed numeric offset from client.
The zz format is for showing timezone in character format (e.g. PDT, PST, EST, etc) which is relevant when we have a timezone like Europe/Berlin instead of a fixed numerical offset.
Another approach
Push raw dates to client and do client-side formatting. Downside is less control and consistency and more js to push to the browser. moment will also run client side if you like.
I just configure my formatters server-side based on user locale and user prefs and then expose those formatters for use in my pug templates in express. So far it works pretty well for me.
Funny Story
I had a co-worker that manually set the wrong timezone on their computer and so the time was wrong. Instead of fixing the timezone they disabled network time and manually set the time to be the "correct" time.
Then they got grumpy when everyone was showing up to meetings they scheduled an hour late.
So yeah...no guarantees the client-side time or timezone offset will be correct.
The reality is, even if you have got the timezone offset, it doesn't mean you have the the correct time on client side, considering some area have "daylight saving time".
But, you could "guess" which timezone the user is in, considering the following data:
req.get('Accept-Language'), for which country is the user may live in now;
req.ip, to search in a database and find out the approximate location;
client-side (new Date).getTimezoneOffset(), for timezone offset;
Finally, through the calculation of the above result, your guess should be almost there. The timezone should be stored in string like 'America/New_York' but not a timezone offset number.
http://momentjs.com/timezone/ should be a good tool to deal with timezone.
After you save the "almost correct" timezone, don't forget to leave a place where user can change it.
Some people like using the library momentJS for anything dealing with time, but I believe the Date object in Javascript suffices what you are looking for and does not require a library. The getTimezoneOffset is what you will need. I hope this helps! Let me know if you have other questions!
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?
So to clarify why I want to do this: I need to send push notifications to users when it's 7pm in their timezone.
For each registered device, I have a timezone string, like "Europe/Paris".
I'm creating a background job which will run every hour. It should fetch the list of users for which it's 7pm, and send them a notification.
So the question I'd like to answer is:
"Where in the world is it 7pm now"
Edit The important thing is to get the timezone, even if it's not formatted like "Europe/Paris", I can do that conversion manually with an array.
There's no built-in support in Javascript for converting the "standard" timezone names (e.g. Europe/London) to timezone offsets.
You mention push notifications so that suggests you're not running in a browser. If you're using Node.js there's a good library I've used called timezone which uses a local set of timezone spec files to handle conversion between timezones.
Note that timezone specs do sometimes change, for example when a national government decides with little notice that they're not doing daylight savings this year. It's vital that your local mappings are kept up to date accordingly.
There may be an easier way to do this, but have a database of users, who have a timezone. Then have a hour difference between your notification server, and that time zone. So your server is in pacific time, and the timezone is eastern, it will have a difference of 3.
Use the difference of the time you want, and what it is on your server, to determine the timezone. You want 16:xx it is 13:xx you get +3 hour difference, use that to look up the time zone, then push to all users associated with that time zone.
There may be an easier way, but that way is real simple solution with a db and a little sql knowledge.
EDIT: Also if you dont mind the time delay of using a web api, you should check this out: https://developers.google.com/maps/documentation/timezone/
Whoops numbers were off with the time-zones, Thanks Trent
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.