Prevent dates from being converting when localizing in iOS - ios

I am localizing an app. The app makes calls to an API that I do not have control over. When posting a request to the API, one of the expected values is a date string in the following format:
"Fri, 15 Mar 2019 15:53:14"
When switching application language to Spanish the date is applied to the date parameter as:
"vie, 15 mar 2019 15:48:42"
which makes sense. However, it causes the API to fail. If I had control over it, I would be passing the date in seconds, rather than a string, but unfortunately I do not own the API.
Does anyone know how to prevent dates from being converted when localizing?
Thanks!

On most the formatters, there is locale property which is the locale of the device by default. You can modify it :
dateFormatter.locale = Locale(identifier: "en_US")
Thanks to rmaddy
Prefer "en_US_POSIX" which is invariant in time.
if the US, at some point in the future, changes the way it formats
dates, "en_US" will change to reflect the new behaviour, but
"en_US_POSIX" will not)
https://developer.apple.com/library/archive/qa/qa1480/_index.html

Related

Joda DateTimeFormatter.parseDateTime is failing for General time zone('z')

Confused with the use of General time zone('z'). Joda is failing in below sample code. Can somebody help me to understand why the behavior is like this? How can I parse a date in differnt timezone using this format in Joda?
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
System.out.println(sdf.parse("2019.09.17 AD at 15:29:00 IST"));
DateTimeFormatter pattern = DateTimeFormat.forPattern("yyyy.MM.dd G 'at' HH:mm:ss z");
DateTime dateCtxParamDateTimeObj = pattern.parseDateTime("2019.09.17 AD at 15:29:00 IST");
System.out.println(dateCtxParamDateTimeObj.toDate());
}
Output
Tue Sep 17 15:29:00 IST 2019
Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "2019.09.17 AD at 15:29:00 IST" is malformed at "IST"
at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:945)
Edit: You need to tell Joda-Time what you mean by IST
Thanks go to HarryQ, who pointed me here to where this is documented.
DateTimeUtils.setDefaultTimeZoneNames(Collections.singletonMap(
"IST", DateTimeZone.forID("Europe/Dublin")));
DateTimeFormatter pattern = DateTimeFormat.forPattern("yyyy.MM.dd G 'at' HH:mm:ss z");
DateTime dateCtxParamDateTimeObj = pattern.parseDateTime("2019.09.17 AD at 15:29:00 IST");
System.out.println(dateCtxParamDateTimeObj);
The output from this snippet is:
2019-09-17T15:29:00.000+01:00
Lowercase z in a format pattern string works differently when formatting and when parsing in Joda-Time. Joda-Time can format time zone names for all available time zones, but with default settings it can only parse a few back. Which it can parse is controlled by the default time zone names of the DateTimeUtils class. It comes with a map of 10 time zone abbreviations as documented in the DateTimeUtils.getDefaultTimeZoneNames method (link at the bottom): CST, MDT, GMT, PST, PDT, UTC, EDT, CDT, EST and MST. We can substitute with a different map. What I am doing above is substituting with a map of just one abbreviation for the illustration. This risks breaking other code, so a better approach for most purposes would be to build a map containing both the abbreviations that were there before and that or those that we want to be able to parse too.
The map I provided above assumes that IST is for Irish Summer Time (and on September 17, 2019, Ireland was using summer time (DST)). You hardly meant Israel Standard Time because Israel too used summer time, IDT. A third likely understanding is India Standard Time:
DateTimeUtils.setDefaultTimeZoneNames(Collections.singletonMap(
"IST", DateTimeZone.forID("Asia/Kolkata")));
2019-09-17T15:29:00.000+05:30
You notice that we now get offset +05:30 instead of +01:00, so a different point in time. The ambiguity may also be the reason why Joda-Time refuses to make its own assumption about what you intended and therefore needs us to tell it before it can parse the string.
Original answer
It’s a documented limitation in Joda-Time. From the documentation of DateTimeFormat:
Zone names: Time zone names ('z') cannot be parsed.
Also note that IST and many other time zone abbreviations are ambiguous, so if there is any way you can avoid parsing one, by all means do avoid it. IST may be for Irish Summer Time, Israel Standard Time or India Standard Time, and there’s no guarantee which of them you get, or if you may even get Iceland Standard Time.
If you insist, one possible solution is to follow the advice from the Joda-Time homepage:
Note that Joda-Time is considered to be a largely “finished” project.
No major enhancements are planned. If using Java SE 8, please migrate
to java.time (JSR-310).
The DateTimeFormatter class of java.time (the modern Java date and time API) will attempt to parse a time zone abbreviation. Good luck.
Links
Joda-Time
Documentation of DateTimeUtils.getDefaultTimeZoneNames()
Related question: Why Joda DateTimeFormatter cannot parse timezone names ('z')
Documentation of DateTimeFormat
Joda-Time homepage
SO user HarryQ, who in comments under my answer to this duplicate question pointed me to the documentation of Joda-Time’s default time zone names.
Others
My answer here shows how to control the interpretation of IST while parsing when using java.time.

localizing + customizing the date format of a UIDatePicker

I need to customize and localize the date format of a UIDatePicker's DateAndTime mode, so that it will display the date numbers in Arabic language plus time in 24 hours format and in Arabic numbers too.
the equivalent row in English would be: 2017 11 15 17:00
I've tried all the solutions proposed on SO from changing the locale to changing device language but to no avail.
Let's breaking it down:
For displaying the content of the date picker to be in Arabic language you'd need to set it your desired locale:
The locale used by the date picker.
For changing the format of the date picker, well... it depends on the used locale; As mentioned in the UIDatePicker - Internationalization:
Date pickers handle their own internationalization; the only thing you
need to do is specify the appropriate locale. You can choose a
specific locale for your date picker to appear in by setting the
Locale (locale) field in Attributes Inspector. This changes the
language that the date picker uses for display, but also the format of
the date and time (for example, certain locales present days before
month names, or prefer a 24-hour clock over a 12-hour clock)...
which means that setting the desired locale for changing the language also affects the format date of the date picker.
Roughly speaking, setting both language and format is unavailable for your case, you should choose the desired language or the desired date format.
However, applying the first point (changing the date picker locale):
datePicker.locale = Locale(identifier: "ar")
should leads to the following output:
Also, the following question:
Show Time in 12 and 24 hour format in UIDatePicker on the basis of app settings not on device Settings
is also related to changing the date picker format.

iOS date format with microseconds strange behavior

I have a strange problem with parsing date string. I have a date formatter with format:
yyyy-MM-dd HH:mm:ss.SSSSSSZZ
and date string:
2012-11-09 10:47:01.999804+01
dateFromString method returns nil, but when I change date string to ie:
2012-11-09 10:47:01.989804+01
it works... Does anyone has idea why there is such limit for microseconds value and how can I properly parse dates like the one above?
I could parse that with regex and cut whole SSSSSS part, but generally sometimes I will need to compare dates so they would not be matching and it will cause more problems.
I had no end of niggly issues doing this, finally got it to work but stripped the point seconds off and used the format as follows
#define DATEFORMATSTRINGTIMEZONE #"yyyy-MM-dd HH:mm ZZZ"
a bit like you say. I have to admit a bit more into the project I realized this was a very difficult method of sharing dates and instead adopted epoch time which has saved all headaches I was having regarding timezones... I'd highly recommend it if you have the luxury of changing the incoming data format.
Whilst I'm not sure why yours doesn't parse, I would question the ZZ instead of the ZZZ at the end given you have +01 not +1?
I have finally resolved that issue.
I'm modifying date format and date string to remove microseconds so I can parse date properly. Then I just add microseconds parsed from original date string.

What date format is this?

I have a web service returning JSON data with some date fields but I couldn't recognize the date format to parse this date field.
2010-11-05TNov:10:1288995006 UTC
2010-10-28TOct:37:1288301863 UTC
2010-10-05TOct:33:1286314434 UTC
That is a quite weird timestamp, isn't it.
yyyy[-]mm[-]dd"T"hh":"mm":"ss.nnnnnn"Z" is an ISO standard date format (ISO 8601), which is similar to what appears in the first field of that... but it has what appear to be three field groups, holding what appear to be:
yyyy-mm-dd"T"MMM:??:POSIX-TIMESTAMP UTC
The current time being 1292563122, those would appear to have been generated 3,568,116 seconds (or approximately 41 days) ago.
Hope this helps.
The first epoch (1288995006) translates to
Fri, 05 Nov 2010 22:10:06 GMT
Seems, somebody obfuscated or messed up the human readable month part - 22 would make more
sense than Nov. If you care about the date, I'd suggest you go with the epoch.
Sidenote:
If a date and a time are displayed on the same line, then always write the date in front of the time. If a date and a time value are stored together in a single data field, then ISO 8601 suggests that they should be separated by a latin capital letter T, as in 19951231T235959.
http://www.cl.cam.ac.uk/~mgk25/iso-time.html
I think you are asking the wrong people. You should really be asking whoever is responsible for creating the web service where there documentation is and / or what format the timestamps are supposed to be.
(FWIW - I agree with the consensus that the timestamp format is probably erroneous.)

What's the best way to detect date formats in user submitted data?

I'm reading csv data uploaded by users in my Ruby on Rails app. When a user specifies that a particular column has dates(or times), I want to be able to automatically detect the format. This means it can be in American or British formats (any of dd/mm/yy, mm/dd/yy, yyyy-mm-dd, 12 Feb 2010, etc etc)
I have tried parsedate in Ruby but it doesn't work for both American and British dates, unless you specify the format. Is there any way to really do this properly, or am I asking for too much? I don't mind calling a script in another language just for this one task. I'm wondering how it's handled in programs like Excel and Google docs.
Unless the application has a locality I don't know how you can determine this accurately.
What you do know however is that:
There are only 12 months.
Only years can be 4 digits long.
If it contains text then it must be the month.
You could write your own parser with these rules to work it out. It could however (without application locality) misinterpret 05/10/2010 as UK 5th Oct 2010 or US 10th May 2010.
there is little that a program can do to magically determine which type of short date format it is.
If you give a program a date like 09/06/08, it could mean either:
9th of June, 2008, or
6th of September, 2008, or perhaps even
8th of June, 2009.
When Ruby parses dates from string, it will use the default format providers to determine what format the date is in. See the Ruby DateTime class documentation for more info.
I think the best thing to do in your situation would be to try and arrange all of your records in to groups, where each group has one particular format of date. If you yourself can't manually determine the difference between the American and British dates by some criterion, unfortunately a program won't be able to either.
However... if each user is from a specific locale, and you can make the (rather large) assumption that every date they upload in a CSV conforms to their country's date format standards, you could make use of the internationalization API. It should be technically possible to grab that particular user's locale, and then load up the correct i18n data (with the appropriate date formatter), and parse the file using the formatter i18n provides you. Read the Rails Internationalization API guide to get an idea of how you can utilize the i18n API.
I know this is an old post but for archives' sakes I recommend using the Chronic gem for parsing dates/times in CSV imports.
Chronic.parse("8/15/2020") # => 2020-08-15 12:00:00 -0000
Chronic.parse("15/8/2020") # => 2020-08-15 12:00:00 -0000
Chronic.parse("8-15-2020") # => 2020-08-15 12:00:00 -0000
Chronic.parse("8-15-2020 3PM") # => 2020-08-15 15:00:00 -0000
FYI you'll want to tell Chronic to parse in the client's account timezone. Otherwise it will use the globally configured timezone (which is UTC in my example).

Resources