Timezone conversion from MST to target timezone not working in Perl - perl

my $apptStartDateTime = "20210401100000";
my $formatter = DateTime::Format::Strptime->new(pattern => "%Y%m%d%H%M%S", time_zone => "MST");
my $dt_obj = $formatter->parse_datetime($apptStartDateTime);
$dt_obj->strftime("%Y%m%d%H%M%S"), "\n"; #prints 20210401100000
# to convert to a different zone:
$dt_obj->set_time_zone("America/Los_Angeles");
$dt_obj->strftime("%Y%m%d%H%M%S"), "\n";#prints 20210401100000
The above does not convert from MST to America/Los_Angeles. Can someone please help? I am new to Perl. Also, would the above code take care of DST?

I think you meant to use US Mountain Time, which is identified by America/Denver. But even if the date-time is in US Mountain Time, that won't always give you the right answer.
If you refer to this list of tz database time zones, you'll see that
US Mountain Standard Time (MST) is UTC-7.
US Pacific Time (America/Los_Angeles) is UTC-8 in the winter, and UTC-7 in the summer.
The correct conversion of
2021-04-01 10:00:00 -07:00 (MST)
is therefore
2021-04-01 10:00:00 -07:00 (America/Los_Angeles)
DateTime properly converted the date-time.
Maybe you meant to use US Mountain Time, which is identified by America/Denver (UTC-7 in winter, UTC-6 in summer). However, that introduces an ambiguity. For one hour every year, you'll get the wrong answer due to the overlap during the DST change.
For example,
2020-11-01 02:30:00 (America/Denver)
could refer to both
2020-11-01 02:30:00 -05:00 (America/Denver) Before "fall back"
2020-11-01 02:30:00 -06:00 (America/Denver) After "fall back"
Date-times should be transmitted in UTC or provide the offset from UTC of the date-time. For example, using the standard RFC3339 format, you could use any of
2020-11-01T02:30:00-05:00
2020-11-01T07:30:00+00:00
2020-11-01T07:30:00Z
for the former and any of
2020-11-01T02:30:00-06:00
2020-11-01T08:30:00+00:00
2020-11-01T08:30:00Z
for the latter. Then, you could keep using DateTime::Format::Strptime (with %z), or use DateTime::Format::RFC3339.

Related

Display local timezone not GMT offset [duplicate]

I want to display the following string on my time axis:
"GMT/BST"
Here's the code:
NSDateFormatter *dateformatter=[[NSDateFormatter alloc] init];
[dateformatter setDateFormat:#"zzz"];
timeZoneString = [NSMutableString stringWithFormat:#"%# / %#",[dateformatter stringFromDate:startDate],[dateformatter stringFromDate:endDate]];
But this gives "GMT/GMT+01:00"
What is the NSDateFormatter code to turn "GMT+01:00" into "BST" ? I can't get the right formatters to do this, having tried z|zzz|Z|ZZZ|v|V see... http://waracle.net/iphone-nsdateformatter-date-formatting-table/
Turns out there is a built in array of 48 time zone abbreviations (e.g. 'BST') in iOS.
NSDictionary *tzDict = [NSTimeZone abbreviationDictionary];
There is an array of 419 time zone names in this array (e.g. 'Europe/London'):
NSArray *timeZoneNames = [NSTimeZone knownTimeZoneNames];
tzDict contains the abbreviations for daylight saving time for a subset of time zone names. So the algorithm would be to check if we are in DST, then see if tzDict has an entry, and subsitute that or if not, use
[NSTimeZone abbreviation];
Here are a few other topics on time zones in general.
Daylight saving time and time zone best practices
How can I map tz database names to city and country names?
C# british summer time (BST) timezone abbreviation
http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
GMT timezone conversion in objective c
I spent a day on this and wanted to make sure so others don't get hung up on it.
For a UK region/locale, the 'z' field pattern in DateFormatter returns the proper string for the "America/London" timezone (e.g. "GMT" or "BST"). However, if you use the US region/locale, 'z' will give you "GMT+1".
The gotcha happens when an abbreviation for the given target timezone with a given locale doesn't exist. I was using the 'v' field pattern, and with the US region, "Europe/London" was falling back to "United Kingdom Time", which blew up my text label. 'z' is better, it falls back to "GMT+1" while in DST, but still not the desired "BST".
The abbreviationDictionary doesn't consider daylight savings time. It's meant to map an abbreviation to a timezone. You'll find "BST":"Americal/London", but this only applies while observing daylight savings time as mentioned by #Nick T. During standard time, Brits are used to seeing "GMT".
Unfortunately, without recreating timezone functionality yourself, you're left with compromises. I think iOS can do better here.
Reference
Date Field Symbol Table as part of the Unicode Technical Standard

perl DateTime and non-existent time user input because of DST clock forward

In a scenario where we know the timezone of the user and the date but the time is input by the user in a textbox (i.e. a calendar where an user selects the date but types the time), after it is properly parsed and we know the hours and minutes, how should we deal wih a non-existent time because of DST clock forward (eg. 02:00 does not exist because of clocks are turned forward 1 hour) in order to pass it -at least an existent hour- to DateTime->new();?
use DateTime;
$dt = DateTime->new(
year => $year_userinput, #2016
month => $month_userinput, #03
day => $day_userinput, #27
hour => $hour_userinput, #02
minute => $minute_userinput, #30
second => 0,
time_zone => $timezone_userinput, #Europe/Berlin
);
Error: Invalid local time for date in time zone: Europe/Berlin
As you go into Daylight Savings, there's no problem. Assuming DLS starts at 2am on a given day in the fictitious time zone, ATZ (a timezone) with an offset of N hrs, then the three seconds commencing one second before 2am are timestamped;
1:59:59 ATZ +N
3:00:00 ADZ +(N+1)
3:00:01 ADZ +(N+1)
...and when coming out of Daylight savings ...
2:00:00 ADZ +(N+1)
2:00:01 ADZ +(N+1)
...
... about an hour later
...
2:59:59 ADZ +(N+1)
2:00:00 ATZ +N
2:00:01 ATZ
There appears to have been an earlier "2:00:01" but that included an offset of (N+1) - or was in the timezone ADZ - whereas this one is in ATZ (N). The DateTime module raises the issue like this:
Ambiguous Local Times
Because of Daylight Saving Time, it is possible to specify a local time that is ambiguous. For example, in the US in 2003, the transition from to saving to standard time occurred on October 26, at 02:00:00 local time. The local clock changed from 01:59:59 (saving time) to 01:00:00 (standard time). This means that the hour from 01:00:00 through 01:59:59 actually occurs twice, though the UTC time continues to move forward.
To avoid the issue, you are going to have to always include the timezone or offset when creating time objects. To do that, you need to use the date (you said you had it) to detect that it is end-of-DLS day and, if the user has chosen a time within the critical hour, you're going to have to prompt for "is that 2:30am ADZ or 2:30am ATZ?" or something similar. Likewise, if it's start-of-DLS, your interface has to refuse entries referencing the critical hour.
Earlier in the doco for DateTime, there's the suggestion - for performance reasons - of determining the local timezone once and then using it throughout your app;
our $App::LocalTZ = DateTime::TimeZone->new( name => 'local' );
... # then everywhere else
my $dt = DateTime->new( ..., time_zone => $App::LocalTZ );
... but this is going to leave you vulnerable to the issue again. Since your interface is going to have to know its start-of-DLS day or end-of-DLS day, you can set and use $App::LocalTZ as advised and then override with the specific, prompted-for Timezone if it's end-of-DLS day.

BlackBerry date parsing and an hour's difference

Due to the limitation of date parsing on BlackBerry I'm trying to roll my own parse/deparse methods, however I seem to be falling foul of an hour's difference somewhere, somehow.
I do this:
long nowLong = System.currentTimeMillis();
String nowString = DateParser.longToString(nowLong);
Date nowDateFromString = DateParser.stringToDate(nowString);
Date nowDateFromLong = DateParser.longToDate(nowLong);
When outputted in order it produces this in console:
[139.46] 1369132556831
[139.46] 21 May 2013 11:35:56 Europe/Dublin
[139.46] Tue May 21 12:35:56 Europe/Dublin 2013
[139.46] Tue May 21 11:35:56 Europe/Dublin 2013
My simulator's time is set to 11:35 so the third statement - DateParser.stringToDate() - seems to be failing somewhere.
Here is my implementation:
public static Date stringToDate(String date) {
long l = HttpDateParser.parse(date);
Date d = new Date(l);
return d;
}
As my nowString includes the time zone I'd expect HttpDateParser.parse() to take this in to account but it seems not to be.
How can I correct this?
HttpDateParser.parse() is documented to handle "GMT" or a "TZD" which I assume to be a "time zone designator". I suspect this is expected to be the (horrible, ambiguous) abbreviation format - so for example, it might be worth trying to parse
21 May 2013 11:35:56 BST
and seeing what you get out. That would at least take you further in terms of diagnosing the behaviour of HttpDateParser. Keeping the time zone's TZDB ID is a better idea in my view, but you may well need to write your own parsing code. You still need to handle local time ambiguity though, where a particular local time occurs twice due to DST transitions.
It's not entirely clear what the input or expected output are in your case - how much control you have over the format. I'd try to use ISO-8601 as far as possible, with a time zone identifer as well if you need one. (If you're only trying to represent an instant in time, I'd use an ISO-8601 representation of the UTC instant, complete with a Z suffix to indicate UTC.)

facebook and his start_time dates

I'm having a lot of troubles playing with the facebook API recently:
I'm fetching start_time from an event and I get this:
2012-11-14T04:00:00+0000
Which is pacific time I think since the event occurs the 13th at 7pm in France (my timezone).
How do I convert this to my timezone?
PS:I use PHP
EDIT: I've found a work around that doesn't work all the time, I just write
date_default_timezone_set('America/Los_Angeles');
before using the dates functions. But it doesn't work for some modified dates. Although I really think it comes from facebook... unfixable bug?
$time = '2012-11-14T04:00:00+0000';
$dt = new DateTime($time, new DateTimeZone('PST'));
$dt->setTimezone(new DateTimeZone('CET'));
echo $dt->format('Y-m-d H:i:s'); // 2012-11-14 05:00:00
Facebook uses the ISO 8601 time format.
The +0000 at the end means it is UTC time not pacific time.
date_default_timezone_set('California');
Try California timezone. Works pretty good for me.

iPhone NSTimeZone: localTimeZone confusion

From what I understand, calling
NSLog(#"Local Time Zone %#",[[NSTimeZone localTimeZone] name]);
gives you the local time zone of the device. What it's giving me is "US/Central", and I can't find that anywhere in the list of abbreviations in [NSTimeZone abbreviationDictionary], or the list of time zone names in [NSTimeZone knownTimeZoneNames]. Where is this one coming from? I need to pass the current device time zone to a Rails app, and it understands things like "Australia/Sydney" or "America/Chicago", but not "US/Central".
How do I take what localTimeZone is giving me and convert it to a string that Rails can understand (i.e. any time zone in knownTimeZoneNames, which is supposed to be all time zone names that the system knows about?)
You're likely using ActiveSupport::TimeWithZone without having required the tzinfo gem:
$ irb -rrubygems -ractivesupport -rtzinfo
>> Time.send(:get_zone, "US/Central").now
=> Tue, 17 Nov 2009 04:27:23 CST -06:00
If you don't require tzinfo, you'll only get a subset of timezones which is fairly useless.
EDIT: Just to avoid confusion, the reason I used the private Time#get_zone API is because that's what's being used behind the scenes when you call Time#zone=. If you don't require tzinfo, calling Time.send(:get_zone, "US/Central") returns nil.
Are you getting that from within the simulator?
If so what does this command returns for if you run it from a terminal?
$ systemsetup -gettimezone
The timezone setting GUI in Mac OS 10.5 would set timezones to US/*. If you manually set it from the console you can set it to one of the expected timezones.
Run this to get a list of the valid, and notice that US/Central isn't among them.
$ systemsetup -listtimezones
Run this to set it to America/Chicago
$ systemsetup -settimezone America/Chicago