2
votes

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

2

2 Answers

3
votes

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.

-1
votes

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!