12/24-hour mode conflict
Asked Answered
W

4

6

I am a French Android developer, so using Locale.getDefault() causes my DateFormat to use a 24-hour mode. But, when I set manually my device to 12-hour mode via the setting menu, DateFormat keeps going in a 24-hour format.

On the contrary, TimePickers are set according to my own 12/24-hour setting.

Is there any way to make DateFormats behave the same way as TimePickers ?

EDIT:

Here is my DateFormat declaration:

timeFormat = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault());

And here is where I set my TimePickerto 12 or 24-hour mode.

tp.setIs24HourView(android.text.format.DateFormat.is24HourFormat((Context) this));

My Solution:

According to @Meno Hochschild's answer below, here is how I solved this tricky problem:

boolean is24hour = android.text.format.DateFormat.is24HourFormat((Context) this);
tp.setIs24HourView(is24hour); // tp is the TimePicker
timeFormat = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault());
if (timeFormat instanceof SimpleDateFormat) {
    String pattern = ((SimpleDateFormat) timeFormat).toPattern();
    if (is24hour) {
        timeFormat = new SimpleDateFormat(pattern.replace("h", "H").replace(" a",""), Locale.getDefault());
    }
    else {
        timeFormat = new SimpleDateFormat(pattern.replace("H", "h"), Locale.getDefault());
    }
}

After this, timeFormat will correctly format dates whether your device is set to display times in a 24-hour format or in a 12-hour one. And the TimePicker will be correctly set too.

Weakling answered 22/4, 2014 at 14:18 Comment(4)
Do you specify your own format? Pay attention between 'hh' and 'HH' docs.oracle.com/javase/7/docs/api/java/text/…Retractor
Please post some code. The part where you set the SimpleDateFormat.Hostility
If you could please post the string you are using for SimpleDateFormat that would be helpful.Doykos
Ew, my bad. It isn't a SimpleDateFormat, but a DateFormat. Just edited to correct this.Weakling
G
6

If you have specified a pattern in SimpleDateFormat then you have fixed the 12/24-hour mode, either 12-hour-mode in case of pattern symbol "h" (1-12) or 24-hour-mode in case of pattern symbol "H" (0-23). The alternatives "k" and "K" are similar with slightly different ranges.

That said, specifying a pattern makes your format independent from device setting!

The alternative would be to use DateFormat.getDateTimeInstance() which makes the time style dependent on system locale (if Locale.getDefault() might change - or you have to deploy a mechanism how to ask the current device locale and then to set in Android-Java Locale.setDefault()).

Another idea specific for Android is to ask directly the system settings using the string constant TIME_12_24 and then to specify a pattern dependent on this setting. This also seems to be possible by special method DateFormat.is24HourFormat() (note for your attention that Android has TWO different classes with name DateFormat). Concrete example for this approach:

boolean twentyFourHourStyle = 
  android.text.format.DateFormat.is24HourFormat((Context) this);
DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault());
if (df instanceof SimpleDateFormat) {
  String pattern = ((SimpleDateFormat) df).toPattern();
  if (twentyFourHourStyle) {
    df = new SimpleDateFormat(pattern.replace("h", "H"), Locale.getDefault());
  } else {
    df = new SimpleDateFormat(pattern.replace("H", "h"), Locale.getDefault());
  }
} else {
  // nothing to do or change
}

You are of course free to refine the code for possible occurrences of k and K or watch out for use of literals h and H (then parse for apostrophs to ignore such parts in replace-method).

Galosh answered 22/4, 2014 at 15:6 Comment(6)
Unfortunately, I haven't specified any pattern. I'm using java.text.DateFormat constants, as shown above.Weakling
@RichouHunter I have now updated my answer giving a possible solution based on the fact that most DateFormat-objects are internally really SimpleDateFormat-objects.Galosh
Ok, I didn't know that DateFormat were internally SimpleDateFormat. However, I just added one more replace() statement to remove the "AM/PM" marker is case of a 24-hour format. Thanks a lot!Weakling
@RichouHunter Good catch for AM/PM-marker. Tip: You should study the created patterns for different locales (from android repository, coming originally from CLDR) to get more safety about replace-mechanism.Galosh
Is there any other time format than "HH:mm" and "hh:mm a"? It seems a bit disturbing for me imagining other ways to format times…Weakling
@RichouHunter I have not studied CLDR-data yet. And Android repositories are often device-dependent and sometimes deviate voluntarily from CLDR, so there is no absolute guarantee, hence my tip for extended tests.Galosh
C
1

The Original Solution, doesn't work well always. My solution is easier and elegant:

Locale.US By default is 12 hours, then we set as 12 hours.

We check if the user has checked 24 hours format, then we set a Locale with 24 hours as default.

boolean twentyFourHourStyle = android.text.format.DateFormat.is24HourFormat(context);
DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US);
if (twentyFourHourStyle) {
    timeFormat = DateFormat.getTimeInstance(DateFormat.SHORT,Locale.FRANCE);
}

Solved with 3 lines ;)

Capitalization answered 2/12, 2014 at 0:59 Comment(2)
Please put an explanation with your answer.Interracial
Welkom to SO! Please put an explanation with your answer, in what way this solves the original question: "Is there any way to make DateFormats behave the same way as TimePickers".Mulct
H
0

Make sure you use correct DateFormat class.

Use android.text.format.DateFormat.getTimeFormat(context);

This correctly updates, when you change the Time 12/24 format in Settings.

Do not use: java.text.DateFormat. This does not work.

e.g. Date date = new Date(); String time = android.text.format.DateFormat.getTimeFormat(context).format(date);

Haler answered 17/4, 2016 at 23:58 Comment(0)
I
0

I realise this is an old problem but I'm here because DateFormat.getTimeInstance(DateFormat.SHORT) wasn't working for me either. It was fine with an API 26 (Android O) AVD but it wasn't working with my old API 16 and API 19 devices (Android 4). So it looks like the issue is just a bug with the older code. I'm now using android.text.format.DateFormat.getTimeFormat() combined with android.text.format.DateFormat.is24HourFormat() to get the correct time picker. That works on both my AVD and both my old devices.

Interlaminate answered 26/8, 2017 at 16:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.