I'd like to use one single timezone for an angular.js application. I'm aware that angular.js currently uses browsers timezone settings for date formatting, but I'd like to override this setting so that I can enforce a specific timezone for a user so that it doesn't depend on a browser settings.
It is a business application in question so there is no need for user specific timezones. Everything happens in a company's specified timezone and this is why I'd like to enforce it for every user. Data is saved in UTC, but it needs to be shown in company timezone for every user without depending on user location/locale/browser settings.
Is there any way I can accomplish this that anyone is aware of? And if there is, it'd be greatly appreciated to point me to correct way to do it :) So far I've had zero luck with it.
You can use a library such as timezone.js, or moment.js. I've used timezone successfully, and I've heard moment.js works pretty well. You'll likely want to make an injectable factory..
angular.module('date', [])
.config(function () {
timezoneJS.timezone.zoneFileBasePath = '/tz';
timezoneJS.timezone.init();
})
.service('dateConverter', function () {
return {
toDisplayDate: function (utcDateIn) {
return new timezoneJS.Date(utcDateIn, 'America/Los_Angeles')
}
}
});
That's just off the top of my head, but it's an example of what you'll probably have to do - convert dates from native JS to the library dates.
Sorry, but it's not possible to change the time zone behavior of the JavaScript Date object. It will always use the time zone of the computer that it's running on.
The best you can do is work around it with one of the libraries listed here. Stephen's answer shows how you can integrate one of them in to Angular.
Also, I'd consider very carefully when you say "there is no need for user specific timezones". Sometimes, that is the case, but very rarely. Often, companies have locations in multiple time zones, or they have employees that travel, or they interact with customers or partners that are in different time zones.
Besides, if what you say is true - that users are always in the single time zone of the company, then wouldn't that already be the local time zone for their computer? If so, then there's not much to do.
If you have users in other time zones, but you wish them to use the company's primary time zone, then that would be a case that would require one of these libraries. But consider carefully the impact of that. Depending on how far away a user is, even their current date might be different than the company's date.
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?
In order to invoke various instance methods of goog.i18n.TimeZone, I've tried pretty good number of combinations of goog.require() and goog.inherits() but still didn't reach the goal. Please can someone let me know what should be the correct way to do that?
Already done with Google Closure Library documentations. So it would be helpful if a demonstration with "Example.js" is shown.
I've found one of the best ways to learn the closure library is to look at the unit tests with-in
the library itself. If you haven't already done so, clone "https://github.com/google/closure-library/". You can then look in: "https://github.com/google/closure-library/blob/master/closure/goog/i18n/timezone_test.js". Look for any of the
unit test methods in the test class that match your use-case. For example, simple time zone:
function testSimpleTimeZoneZero() {
var date = new Date();
var simpleTimeZone = goog.i18n.TimeZone.createTimeZone(0);
assertEquals(0, simpleTimeZone.getOffset(date));
assertEquals('GMT+00:00', simpleTimeZone.getGMTString(date));
assertEquals('Etc/GMT', simpleTimeZone.getTimeZoneId());
assertEquals('UTC', simpleTimeZone.getLongName(date));
assertEquals('UTC', simpleTimeZone.getShortName(date));
assertEquals('+0000', simpleTimeZone.getRFCTimeZoneString(date));
assertEquals(false, simpleTimeZone.isDaylightTime(date));
}
The other aspect of the timezone class you must be aware of is that it required "data" to operate.
from the documentation "https://google.github.io/closure-library/api/goog.i18n.TimeZone.html":
i18n.TimeZone Extends
TimeZone class implemented a time zone resolution and name information source for client applications. The time zone object is initiated from a time zone information object. Application can initiate a time zone statically, or it may choose to initiate from a data obtained from server. Each time zone information array is small, but the whole set of data is too much for client application to download. If end user is allowed to change time zone setting, dynamic retrieval should be the method to use. In case only time zone offset is known, there is a decent fallback that only use the time zone offset to create a TimeZone object. A whole set of time zone information array was available under http://go/js_locale_data. It is generated based on CLDR/ICU and Olson time zone data base, and will be updated timely.
The unit test shows a mechanism to "load" this data statically (at the top of the file).
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 was writing a chrome extension this morning and the everything seems fine.
However by night time I had noticed that the time being displayed is wrong.
At first I thought it was a code problem but after going onto their site it seems like every single places the time were all displaying my local time.
Is anyone experiencing this same problem?
Or should I consider changing the library all together...
I've recorded a video here
http://youtu.be/g6n6nXJt_uU
function setClock()
{
now = moment.tz(moment.tz().format("MM/DD/YYYY hh:mm"),
"EST").format("MM/DD/YYYY hh:mma");
document.getElementById("time").innerHTML=now + " NYC";
}
console.log(moment.tz("EST")._d);
console.log(moment()._d);
setClock();
setInterval(setClock,1000);
CodeOutputHere
Regarding your code:
You should not use time zone abbreviations like EST for this purpose, since time zone abbreviations are often ambiguous. If you're looking to set US Eastern Time, then you should be using the IANA time zone identifier of America/New_York.
EST only exists in the tzdb for backwards compatibility purposes. Arguably, it should be left out of the moment-timezone data.
Calling moment.tz() without any argument is not recommended. You should just call moment().
Your code appears to be formatting a moment, then parsing it into another moment, then formatting it out again. There's no reason to jump through so many hoops.
You should not use the _d property. That is meant to be internal to moment.js. (It should probably be hidden by closure, but it's not). Instead, use .format() or one of the other public functions.
Ultimately, I think you are simply after:
var now = moment().tz('America/New_York').format("MM/DD/YYYY hh:mm");
I highly suggest you re-read the moment-timezone and moment.js documentation.
Regarding the moment-timezone web site with the map - you're correct that there's currently a bug with the demonstration web site. It is not a bug with the library itself. I'll investigate and report that to the moment team.
I have a table that needs to display a date/time in the client's timezone. However, I am having a hard time finding a way to do this effectively. I know I can use client side javascript to get the timezone (and that this method is a little flaky), but I need it in the Page_Load event, so I can't call javascript beforehand.
I can get it from a separate page (at login for example), but that doesn't always work, because sometimes people use bookmarks directly into internal pages, and bypass logon with a cookie.
So I am left a few choices:
1. Have a cache per user for the last timezone that I fill up at every opportunity from a postback with no guarantee it will be right)
Try some weird IP geolocation hack
Have a user profile that allows the user to set their timezone (again, if they travel this won't always be right either)
Try some funkly page redirect to force the postback, (but some browsers disable page redirects)
Have the user explicitly set the TZ
Do the tz formatting in Javascript
None of these are ideal, it seems to me to be info the Browser should be providing the server. Does anyone have any other suggestions?
If possible, display times relatively. Rather than showing a particular time, use prose like, "5 minutes ago," or "Last week."
If you must display an absolute time in the client's time zone, based on your comments I'd go with option #5, sending UTC time down to the browser and then displaying local time using JavaScript. From your description it sounds like users can visit the page(s) that need to display the time in their time zone without having logged in, so storing it in the user profile seems inadequate.
I discuss the relative time display concept in more detail in Advice for Storing and Displaying Dates and Times Across Different Time Zones, as well as provide a simple extension method on the DateTime structure for adding a ToRelativeDateString method so that you can write code like:
string relativeTime = myDateTimeVariable.ToRelativeDateString();
Hope this helps...
I would use a mixed strategy:
Users can set the timezone in their profiles
Default is "auto" which means: format with JavaScript
Keep the timezone in the user profile however on each page that you display it (or in the master page) give the user the ability to adjust it. Once its adjusted allow it to persist for the remainder of the session and if they want it set then they will need to set it in their profile.
5, 2, 3, 4, 1 is probably the best order of your options.
Just output all times in UTC and then transform to local time at client side.
I would have to agree with Scott Michael. Display relative time, if you need absolute times your browser already knows how to localise them from UTC.
But if you're looking for detecting timezones robustly with javascript (for use server side); check out jsTimezoneDetect. It will give you an Olsen timezone key that you can use with server side normalizations of datetimes.
I thought I'd give you an update. I did take up the various suggestions of formatting the date on the client side (or more specifically reformatting it.) As google fodder I have put a full explanation of this at the end of this post.
However, the problem is that Date.toLocaleString takes no parameters to control the formatting, and so, in my US locale anyway, I get a big bulky string "Saturday, November 27, 2010 3:58:38 PM" This is way too bulky, I want a compact format like Sat 11/27/10 3:58PM" but there is not way to control it AFAIK.
So I am going to modify to try to cache the time zone in the session based on input from the various key pages posting back the timezone offset, and include the ability to modify the tz in the user's profile. It is not nice, but it is the best I can come up with. Like I say, this really should be included in the browser's http headers.
----- Formatting on the client side ------------
So I have labels like this (in a ListView FWIW):
<asp:Label ID="TimeLabel" runat="server" class="UTCTimeCell Hidden">
<%# Eval("when") %> UTC
</asp:Label>
Note you have to include UTC for the timezone since the default ASP.NET formatter does not include it. (Here I am assuming you are storing your dates as UTC, which in nearly all cases you should.) Note Hidden is a standard css class I used with display:none.
Then I define the following functions in my utilties javascript (obviously I use jQuery...)
function timeFormatLocal(timeStr) {
var dt = new Date(timeStr);
return dt.toLocaleString();
}
function timeReformatLocal(selector) {
$(selector).each(function () {
$(this).html(timeFormatLocal($(this).html()));
});
}
then in my page ready event I use something like this:
timeReformatLocal(".UTCTimeCell");
$(".UTCTimeCell").removeClass("Hidden");
This reformats those label cells to the locale based format.