iPhone NSTimeZone: localTimeZone confusion - iphone

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

Related

How to set up only time in date-fns and still keep the timezone in javascript

I currently have the following use case:
User receives a date in UTC from the backend
This date is transformed into local time for displaying purposes
The date is displayed in different inputs. One input for date and other for time
User can select time independently
The date should be sent back to the backend in UTC format as well
I'm not very experienced with time zones and I'm getting beaten by trying to allow the user to set up only the time (or date) in a datetime field.
My pseudo code is the following:
When receiving the from backend simply convert the date to show it to the user, making the orignal date stay in UTC
When the user picks the hour and minute (all in one action) use setHours and setMinutes from date-fns library
Use native toISOString() to set in models
Code so far [playground]:
import { utcToZonedTime, format } from "date-fns-tz";
import { setHours, setMinutes } from "date-fns";
const UTCStringdate = "2022-04-06T10:00:00.000000Z";
const userTimezone = "Asia/Bangkok";
const localizedTime = utcToZonedTime(UTCStringdate, userTimezone);
// Prints the correct information
// 10:00 in UTC is equal to 17:00 in Bangkok
console.log(format(localizedTime, "HH:mm"));
// Now I expext to set only the `minutes` and `hours`
// to this `localizedTime` so that I can update the backend
const [hours, minutes] = "10:30".split(":");
// Somewhere over here the `setHours` and `setMinutes`
// is turning the Date object into my own timezone
// and not using `Asia/Bangkok` timezone anymore
let newTime = setHours(localizedTime, hours);
newTime = setMinutes(newTime, minutes);
// Now I expect to print 17:30 since we only
// set up 30 minutes forward than the original one
// but it ends up printing 10:30
console.log(format(newTime, 'HH:mm'));
I understand that somewhere along the way (most likely in setHours and setMinutes) the date-fns library turns back the localizedTime back into my own timezone, completely ruining the idea of turning the Asia/Bangkok time into UTC.
Questions
First, is this the best approach to manipulate only the time part of a date when considering timezones? If not, anyone can point me to articles? I wasn't able to find anything on the topic
Second, how can I use setHours and setMinutes and still maintain the timezone?
There are no multiple time zones in JavaScript. There is UTC and there is your local one. What date-fns-tz does, is adjusting the time to the chosen user time zone. In your example, you can see this when printing both the original and the localized time
const utcTime = new Date(UTCStringdate);
console.log(utcTime.toISOString()); // -> 2022-04-06T10:00:00.000Z
console.log(localizedTime.toISOString()); // -> 2022-04-06T14:00:00.000Z
To solve your issue, convert UTC time to users time and let the user to adjust hours and minutes in his local time zone. After that, convert the time object back to UTC using zonedTimeToUtc
newTime = zonedTimeToUtc(newTime, userTimezone);
and then use newTime.toISOString() to send it back to the server.
console.log(newTime.toISOString());

Flutter: DateFormat.parse returning wrong time at midnight only on Desktop Win32

I'm trying to parse a string into a DateTime in flutter.
On android, iOS and Web the procedure works perfectly, but on windows it keeps returning, only at midnight, the wrong time.
DateFormat('HH:mm').parse('00:25');
returns 1970-01-01 01:25:00.000 on windows, but 1970-01-01 00:25:00.000 on any other OS, while any hour >= 1 returns the right value.
If I try using parseStrict method, the following happens
DateFormat('HH:mm').parseStrict('00:25');
returns FormatException: Error parsing 00:25, invalid hour value: 0 in it with time zone offset 1:00:00.000000. Expected value between 1 and 1. Date parsed as 1970-01-01 01:25:00.000..
Thanks in advance for any help
Edit: This DateTime is in local timezone, I'm not trying to parse a UTC time. I've noticed, though, that if I add the date, the DateTime seems to get parsed properly.
But I need only the time.
These values are the open hours for a shop.
I know that I SHOULD use TimeOfDay class, but I can't use it because it doesn't have the compareTo method, which I need for my case scenario.
Anyway, I've tried Android, iOS and Web and they all parse the time properly, the only one problematic is Windows

Getting timezone abbreviations in Swift

I am trying to retrieve the timezone abbreviations of the local time zone by using the following code.
private func getLocalTimezone() -> String {
guard let localTimezone = TimeZone.current.abbreviation() else {
return ""
}
return localTimezone
}
But when I am in Indian time zone I am always getting GMT+5:30 where I need it as IST. Its coming correctly when I am in CST or PST. Can anyone please suggest a way to reach to the solution for this issue.
Thanks a lot in advance
This is because time zone abbreviations are locale sensitive. IST only means India Standard Time (Asia/Kolkata) in India. In other parts of the world, it could mean Israel Standard Time, or Irish Standard/Summer Time. Here's a site that shows you the list of abbreviations. You can see for yourself how ambiguous they can be.
This is why abbreviation() takes into account the region of your phone, i.e. this setting:
abbreviation() will give you "IST" if your device's region is India. If your phone is somewhere else, it shows "GMT+5:30" because that is the safest, most unambiguous option.
If you want it to output IST no matter where your device is, you need to hard code this by creating a dictionary of time zone identifiers to abbreviations that you want. There is a built in abbreviationDictionary that goes the other way - abbreviations to identifiers. You can search it, and it will work for IST (Asia/Kolkata), but might not work for whatever other time zone that you are interested in.
let abbreviation = TimeZone.abbreviationDictionary
.first(where: { $1 == TimeZone.current.identifier })?.key
and I'm not sure whether the contents of this dictionary will stay the same in future versions of iOS. Use it at your own risk.

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.)

NSDate date returns 2h less than it should

When i call [NSDate date] it returns 2 hours less than it should. I've checked my computer clock settings and they are all ok. I've checked settings in iPhone and time zone and clock are all OK. Even simulator shows correct time on top toolbar. But when I try to log current date it shows 2 hours less than it should. I ran out of ideas where to look.
All dates returned by [NSDate date] are in the GMT time zone.
When you use any NSDateFormatter, just set the time zone and it will print out the correct time.
Look carefully at the output of the NSLog() statement. You will see that the output always contains the timezone using standard UTC. Therefore, the date is actually correct, taking into account the timezone.
I found my solution here: How to convert time to the time zone of the iPhone device?
So if you ever want to change [NSDate date] to point to local time just use the code provided in the link above. And dont forget to change timeZoneWithAbbreviation on sourceTimeZone from EST to GMT (because NSDate is always in GMT)
Once again thanks everyone for helping out..