If my Android device's Settings>Language & keyboard>Select locale is set to English(United States), dates are formatted m/d/yyyy. If I wish to use format dd/mm/yyyy by selecting Settings>Date & time>Select date format>31/12/2011, my dates remain formatted as m/d/yyyy; Settings>Date & time>Select date format has no effect. I think this is because the DateTimeFormatInfo's UseUserOverride property is always false.
As some (at least one I've found) Android devices only have one English Locale selectable ie, English(United States), it means that non-US users with these devices cannot use their normal date format: dd/mm/yyyy.
Can you please post an example of your Date/Time usage? There are two (or more) Date Time types such as System.DateTime and Java.Util.Date, as well as many ways how those objects could be serialized to strings.
For managed System.DateTime objects, it is not part of Android's Java framework, so it won't take this android-specific settings into consideration. To have your date/time objects under Android settings you should use android-based objects.
If your date/time objects are from Java land, it should be likely serialized as configured by the settings and may be MfA bug if it's not in the expected format in MfA while it is in Java apps.
I'm using Resco's AdvancedList and DetailView components. These use the settings from DateTimeFormatInfo.CurrentInfo.ShortDatePattern and DateTimeFormatInfo.CurrentInfo.ShortTimePattern. These take their date format settings from the device's locale setting but not, apparently, from the device's Settings>Date & time>Select Date format setting. I'm told by Resco that I could override these settings using the AdvancedList/DetailItemDateTime.Format property. However, how do I set this property to the Android-based objects Android setting?
Andrew provided the necessary info in Comment #3. Reopening.
-> Class Libraries
I wonder if this "likely Android-API-only" date/time format customization can be supported in the core System* classes. UseUserOverride can never be used (and should never be used, since it is *really* for user's == application's override, not by the system). And if there is no native (NDK) API for this it is not doable.
Quite a problem for me with MfA 4.4.55.
MfA is just ignoring date format. I have set on device English(United States), but date format to "31/12/2013". DateTime.ToString() and ToShortDateString() still shows in 12/31/2013 format.
Tested on Emulator L17 and Xperia S.
Created attachment 3377 [details]
Simple ToShortDateString() test app
Before running this sample go to Settings->Date&Time->Select Date Format->31/12/2013
Run this sample and you see 12/31/2013.
Tested on various devices and emulators.
The problem is that during process startup we set the locale "by-name" (e.g. en-US), and use Mono's default formatting information based upon the locale name. We don't currently look for or set custom format information, which is the problem/bug.
Which is exactly what we're seeing in Comment #7.
Do you plan to change it in future or we should use Java objects to format Dates ?
According to our experience, many people have Date format set to different from locale default, so now DateTime.ToString() & ToShortDateString() are generally useless in UI (at least without aditional parameters retrieved from android settings and converted to .NET parameters)
( MS implementation allows customization of date formatting, which is reflected in these methods regardless of locale defaults.
> Do you plan to change it in future or we should use Java objects to format Dates ?
For now, use the Java types if this is a problem. We will support custom date and time formats in the future, but I have no timeline for when.
In case some users run into this issue while using Xamarin.iOS, note that this limitation is present in desktop Mono, Xamarin.Android, and Xamarin.iOS.
In all three cases, CurrentCulture.UseUserOverride is set to `true`, but changes to the calendar or time format via the system preferences are not reflected by CurrentCulture.DateTimeFormat.Calendar or CurrentCulture.DateTimeFormat.ShortTimePattern.
Or that was the behavior I observed when I checked it today anyway.
@Brenden: Correct. We currently have no mechanism of listening to "system events" to know when the current culture changes (and do anything when it does).
Even in the Android side of things, even if we did have such a mechanism, I'm not sure what to hookup to in the Android-space to be notified when Culture information is changed by the user. (On Windows, there's presumably some WM_* culture change notification message that's sent to all applications, so at least philosophically I know what could be done on Windows to support such a thing; I have no idea where to start on Android.)
@Jonathan: But can't you read date settings on application start ?
@Michal: Yes, we read them on application start; it's how any localization is done at all. Then we cache the data, and (currently) have no provision to invalidate that cache.
Furthermore, on Unixy systems (not OS X, but Linux/Android/etc.) the $LANG environment variable is used to read the default value. There is no capability within POSIX to change the environment variable of a child process after the child has started, so (from the Gtk#/Xamarin.Android/etc. perspective) "just" re-reading $LANG when we "know" the culture has changed won't actually do any good, as $LANG _cannot_ have been changed.
Just restarting the process is a considerably easier "workaround"...
(Would implementing such an invalidation mechanism be difficult? Probably not. It just hasn't been done yet. The bigger issue, as I alluded to, is figuring out which OS-specific mechanisms we need to listen to for system-wide culture changes, so that we _can_ perform an invalidation, along with providing the updated culture name. This is _probably_ more sanely done in the C# side of things than in libmono, but that would depend upon what the "culture change notification" system is.)
And on that note, I finally got off my ass to figure out how Android bothers to tell apps that the culture has changed:
That's not an entire solution -- after getting the broadcast, is java.util.Locale.getDefault() changed to be the new locale? -- but it's at least a start.
The _real_ problem here (from Xamarin.Android) is one of priority: we have lots of higher priority bugs (crashers, invalid generated Java code, semantically wrong binding code in corner cases, the fact that binding .jar files makes people's eyes bleed and needs to be made "idiot-proof" or at least significantly more resilient to frequently observed behavior...).
As I currently see it, while this bug is annoying it happens sufficiently rarely that there isn't a lot of pressure to raise it's priority. (How often do people start the app in one culture, then change the culture, and return to the app? I have to believe that this scenario is comparatively rare, though any actual evidence to the contrary would be welcomed.)
@MarekS, as per comment 11 above, the basic problem here is that the Mono BCL doesn't support this scenario. If you can think of a way to implement in on desktop with provisions for providing custom behavior for other targets (Android, iOS, others) it would make it possible for us to fix the issue in a uniform way.