2

I am working on a application, which detects the browser's time zone and asks the user's to set the time zone to the browser detected values.

So, I have populated, a select drop down which list all the All the keys present in ActiveSupport::TimeZone::MAPPING.

Now, I have a user whose timezone is (GMT-08:00) Pacific/Pitcairn. There are many such values which are not present in ActiveSupport::TimeZone.

How should I handle such values. I've checked many js files which claim to send in Rails Supported Values, but none of them seem to work.

If I set my timezone to UTC-08:00 in Windows machine then my javascript plugin detects a time zone and sends in a value of America/Los Angeles.

We have a check box to not allow DST Timings on Windows machine. So in this case with UTC-08:00 as time zone and DST box unchecked we're getting a value Pacific/Pitcairn.

So to go with matching before / for two different values of America/Los Angeles and Pacific/Pitcairn it's not possible.

Set the value by UTC offset, by ignoring name also wouldn't help. We have two seperate value with (UTC-08:00) Pacific Time (US & Canada) and (UTC-08:00) for Tijuana. So how do I decide which value to set.

showTimeZoneInfo: function(member_time_zone, timeZoneInfo, invertTZHash){
  var tzValue = jQuery().get_timezone({'defaultvalue' : 'Etc/UTC'});
  var railsOffset = TimeZoneFlash.extractOffset(timeZoneInfo[member_time_zone]);
  var browserOffset = TimeZoneUtils.zoneWithoutDST();
  if ( railsOffset != browserOffset) {
    jQuery(".time_zone_text").text(browserOffset + " " + invertTZHash[tzValue]);
    jQuery('.cjs_display_time_zone').removeClass('hide');
  }
}

Now we have a case where invertTZHash doesn't contain Pacific/Pitcairn. And It returns a undefined value.

I am working on building a alert box for users who are in a different time zone compared to their browser's timezone. Even Intl.DateTimeFormat().resolved.timeZone wouldn't help because most of my traffic is from IE and FF browsers

123
  • 744
  • 2
  • 8
  • 20

2 Answers2

3

Time Zone != Offset. See the timezone tag wiki. So just swapping it for another time zone that happens to be on UTC-8 is not a good idea. You will pick up all the DST rules for that zone, which don't necessarily apply.

Even Pacific/Pitcairn isn't purely UTC-8 if you deal with past dates. It moved from UTC-08:30 to UTC-08:00 in 1998 - you can see that here.

This is one of the reasons I'm not happy with ActiveSupport::TimeZone. They make it quite clear in their docs that it is limited:

Limit the set of zones provided by TZInfo to a meaningful subset of 146 zones.

This seems rather arbitrary. Who is it that determines what is "meaningful" and what isn't? If it wasn't meaningful, it wouldn't have been in the database to begin with!

You should look at using the tzinfo gem, which is what ActiveSupport based theirs on anyway. It has the full TZDB with all of its time zone data instead of a limited subset.

Regarding time zone detection, I'm not sure what JavaScript you are using to "detect" the time zone. You show calling some functions get_timezone and TimeZoneFlash.extractOffset that must be custom to your app or provided by external libraries. Please elaborate on exactly what you're using.

The only timezone detection library for JavaScript that I am aware of is jsTimeZoneDetect - which makes it quite clear that it just takes an educated guess. Unless you are depending on the new internationalization APIs in the very newest Chrome an Opera (which I don't think you are), then there's no guaranteed way to detect a time zone without user involvement. See also this answer.

We have a check box to not allow DST Timings on Windows machine. So in this case with UTC-08:00 as time zone and DST box unchecked we're getting a value Pacific/Pitcairn.

Yes, that is an awful reality. IMHO - that should never be unchecked. It would be better if the checkbox wasn't there. Whether DST applies or not is handled by the time zone, so there's no good reason to disable it. I'm sure that they left it there specifically for cases like Pitcairn, because there isn't a Windows time zone entry for them specifically.

Update

From your comments:

I already have a drop-down for this. I am working on building a alert box for users who are in a different time zone compared to their browser's timezone.

Take the current offset from JavaScript using new Date().getTimezoneOffset(). (It's in minutes, and the sign is reversed, so you may need some simple math.) Compare it to the current offset for the selected time zone in your drop down. (You should be able to get that from your server-side code.)

If they don't match, then alert your user. No need for jsTimeZoneDetect at all for this.

Community
  • 1
  • 1
Matt Johnson-Pint
  • 197,368
  • 66
  • 382
  • 508
  • It's a jquery detect time zone plugin. – 123 Aug 21 '13 at 14:29
  • Ah. Yes, that in turn uses the library I mentioned. It just wraps it up as a jQuery plugin. – Matt Johnson-Pint Aug 21 '13 at 14:29
  • Be sure you understand the limitations of jsTimeZoneDetect. It's just a guess, it's not perfect. Any app that needs to do anything reasonably complex should have a time zone setting that the user can change. You can guess a *default* value, but you should let them change it. If you're looking for a nice way to present a list of time zones, consider [this map-based picker](https://github.com/dosx/timezone-picker). – Matt Johnson-Pint Aug 21 '13 at 14:33
  • I already have a drop-down for this. I am working on building a alert box for users who are in a different time zone compared to their browser's timezone. Even Intl.DateTimeFormat().resolved.timeZone wouldn't help because most of my traffic is from IE and FF browsers – 123 Aug 21 '13 at 14:38
  • Is there a way by which I can populate the existing timezoneHash from rails with all the possible timezones. – 123 Aug 21 '13 at 14:40
  • The most accurate answer is going to come from your dropdown. You have to trust the user on their time zone selection. After all, they usually have control to change it on their computer as well. I could see maybe if the offset is *significantly* off, that you might want an alert - perhaps a mobile user is changing time zones as they move around. For that you should just compare *current* offsets. – Matt Johnson-Pint Aug 21 '13 at 14:47
  • Not sure on the rails question about timezoneHash. – Matt Johnson-Pint Aug 21 '13 at 14:47
  • Looks to me like the only proper answer to this question available now is to use the map-based picker, but that comes with lot of added complexity. – 123 Aug 21 '13 at 14:59
  • The map-based picker is a nice feature. It avoids the problem of users not knowing which time zone to pick from a big drop-down. But there's no reason you *have* to use it. If you take the approach I described in my last update, it won't matter what list you use. But if you want the *full* list, you should get them from the tzinfo gem instead of using ActiveSupport::TimeZone. – Matt Johnson-Pint Aug 21 '13 at 16:53
  • How do I get list of Mappings using TZInfo. – 123 Aug 22 '13 at 05:04
  • By List of Mappings, The format we have in for Rails Mapping described in http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html. I am currently using the Mapping to populate my drop down. But if I use TZInfo gem, it won't solve my problem. – 123 Aug 22 '13 at 05:15
  • Those are proprietary to Rails. The names they chose for their limited subset of zones are not standardized in any way. So with TZInfo, you wouldn't have anything similar and would just use the zone names like `America/Chicago`. IMHO, this is better anyway. You could *borrow* the mappings constant from Rails, but you'd then have to add your own values for the missing zones. – Matt Johnson-Pint Aug 22 '13 at 12:29
  • To get a list of all of the zones from TZInfo, see towards the bottom of [the documentation](http://tzinfo.rubyforge.org/doc/) which gives you options. You could just list them all, or you could first limit them by country if you have that in your app already. – Matt Johnson-Pint Aug 22 '13 at 12:31
-1

First Option: Set by UTC Offset

  1. Get the UTC Offset
  2. Search for UTC offset in your ruby array.
  3. Set value by UTC offset, ignore name. Choose the first timezone which has the correct UTC offset.

Some code for this:

timezone = ActiveSupport::TimeZone.all.select { |tz| tz.utc_offset == my_offset }.first

Second Option: Add a new Timezone to the list

If you know the UTC offset, add a new TimeZone to the list. See Docs.

Hope that helps!

Dan Grahn
  • 8,166
  • 3
  • 33
  • 67
  • The Solution you've answered, doesn't help in my case. If I set my timezone to UTC-08:00 in windows then my javascript plugin detects a time zone and sends in a value of America/Los Angeles. We have a check box to not allow DST Timings, so in this case with UTC-08:00 we're getting a value Pacific/Pitcairn. So to go with mathcing before / for two different values of America/Los Angeles and Pacific/Pitcairn it's not possible. Hope I was clear – 123 Aug 21 '13 at 11:51
  • Yeah... you need to be adding more info then. Please include as much info as possible and read this: [How do I ask a good question?](http://stackoverflow.com/help/how-to-ask) – Dan Grahn Aug 21 '13 at 11:52
  • Do have a look at the above reply, let me know if you haven't understood it. – 123 Aug 21 '13 at 11:55
  • Add this info to the original question. Include code if possible. – Dan Grahn Aug 21 '13 at 11:55
  • Set the value by UTC offset, by ignoring name also wouldn't help. We have two seperate value with (UTC-08:00) Pacific Time (US & Canada) and (UTC-08:00) for Tijuana. So how do I decide which value to set. – 123 Aug 21 '13 at 12:16
  • Choose the first, or check geolocation. – Dan Grahn Aug 21 '13 at 12:18
  • Could you please elaborate what you're suggesting in the first one. Don't find it to be solving my problem. – 123 Aug 21 '13 at 12:28
  • Your suggestion would assume that a Time Zone and an Offset are the same thing, or that `Pacific/Pitcairn` is and always has been fixed at UTC-8. Both are false. – Matt Johnson-Pint Aug 21 '13 at 13:57
  • What is the best way of handling this issue @MattJohnson – 123 Aug 21 '13 at 13:59
  • Time Zone and Offset are the same thing if DST is not included. And... if the user is in one location they will only have one offset. – Dan Grahn Aug 21 '13 at 13:59
  • See my answer. And no - they are still not the same thing. See [the timezone tag wiki](http://stackoverflow.com/tags/timezone/info). And no, there is not only one offset per location. There is one offset, per location, per range of moments in time. – Matt Johnson-Pint Aug 21 '13 at 14:03
  • Perhaps context of the question would help, but it appears that the user is looking for the timezone of the browser. Which will be a set UTC offset once DST is removed. This is true as long as we live in the present and not in 1998. – Dan Grahn Aug 21 '13 at 14:05
  • @MattJohnson Got it even geolocation, will not help in many cases. Looking at how I can use tzInfo. – 123 Aug 21 '13 at 14:17
  • @screenmutt - You are correct that javascript's `Date.getTimezoneOffset` will return just an offset. The problem is that you have no guarantees that it won't be a different offset for another moment in time. Since it's being passed back to a time zone function in ruby, there's a good chance that it's being manipulated. You could easily cross a DST boundary (for zones that have them). And they might be wrong to begin with for [past dates](http://stackoverflow.com/q/16946002/634824). Who's to say we *aren't* working with data from the past? Many applications do exactly that. – Matt Johnson-Pint Aug 21 '13 at 14:27
  • @MattJohnson I think you are on a witch hunt here. Yes, there are differences. However, for this application it appears that the user needs a simple offset. If he would like to chime in on this matter, that would certainly be appreciated. However, due to the fact that he is saving this timezone on the server side and it is ONLY being used to populate a form which a user can then change if it is inaccurate. I still believe that selecting by offset is a valid choice in this case. However, I would prefer that the whole thing was converted to UTC offset if that was, in fact, what he wanted. – Dan Grahn Aug 21 '13 at 14:31
  • Not on a witchhunt, I'm just attempting to provide accurate advice. There are way too many misconceptions about time zones. I appreciate your perspective, but how do you know that's all it is being used for? Simple case example - store the offset, and apply it to a future date. It might be the wrong offset. That's why he's storing `America/Los_Angeles` to begin with - which is a much better approach. – Matt Johnson-Pint Aug 21 '13 at 14:40
  • Let me know if we can sync rails time zone with javascript detected timezones. – 123 Aug 21 '13 at 15:27