2

I am working on SimpleDatFormat on android. I tried to convert time from US locale to Swedish. It is working fine in emulator but when I tested it on Samsung devices it is not working. On rest of the devices and versions it is working fine.

SimpleDateFormat inputFormat = new SimpleDateFormat("hh:mm a", Locale.US);
SimpleDateFormat outputFormat = new SimpleDateFormat("hh:mm a", new Locale("sv"));
try {
    return outputFormat.format(inputFormat.parse(date));
} catch (ParseException e) {e.printStackTrace();}
return null;

Actual Result

Example input :- 06:45 AM

O/p in emulator :- 06:45 FM

O/p in real device :- 06:45 AM

Expected Result

Example input :- 06:45 AM

O/p in emulator :- 06:45 FM

O/p in real device :- 06:45 FM

Note : This issue only happens for Time locale conversion. The date conversion works fine in both real and emulator devices.

Thanks in advance.

Shobhith
  • 505
  • 4
  • 12
  • 1
    By the way… You are using terrible date-time classes that were years ago supplanted by the modern *java.time* classes. – Basil Bourque Nov 17 '22 at 16:24
  • Give example inputs and outputs. Explain how the results do not match your expectations. – Basil Bourque Nov 17 '22 at 16:28
  • If parsing is not a problem, delete from your Question. – Basil Bourque Nov 17 '22 at 16:30
  • Not answering your question, I recommend you consider throwing away the classes `Date` and `SimplerDateFormat`. They are troublesome and long outdated. You should prefer java.time, the modern Java date and time API. If developing for older Android too (below API level 26), you can use it through [desugaring](https://developer.android.com/studio/write/java8-support). – Ole V.V. Nov 17 '22 at 19:15
  • The difference must be due to different locale data in the device and the emulator. Where each gets its locale data from, I don’t know. As an aside, according to [this Wikipedia article](https://sv.wikipedia.org/wiki/12-timmarsklocka) it should be `f.m.` rather than `FM` in Swedish (sorry, everyone, the article is in Swedish too). – Ole V.V. Nov 18 '22 at 03:02
  • Allow me to take a step back and ask: Are you trying a too literal translation of the American 12-hours times that you have got to Swedish where your Swedish users would really be happier with a 24-hour format common in Sweden and among Swedish-speaking people? I believe that standard format/notation in Swedish is like `21:23`. Or are your users telling you that they have these very specific and non-standard wishes for how you display time to them? – Ole V.V. Nov 18 '22 at 03:15
  • [My suggestion in Java code running online.](https://ideone.com/2Mi2fH) – Ole V.V. Nov 18 '22 at 03:45
  • If your users insist on `FM` and `EM` and you want to be sure to give them that, with java.time you may use a `DateTimeFormatterBuilder` and its overloaded `appendText(TemporalField, Map)` method. There’s an example of that in my answer [here](https://stackoverflow.com/a/57183455/5772882). – Ole V.V. Nov 18 '22 at 20:46

2 Answers2

2

First of all, the java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.

Irrespective of whichever API you go with, the most likely cause of the problem is initializing Locale with one parameter. You should use new Locale("sv","SE") instead of new Locale("sv").

Demo with java.time API:

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("hh:mm a", Locale.US);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a", new Locale("sv", "SE"));
        LocalTime time = LocalTime.parse("06:45 AM", parser);
        String formatted = time.format(formatter);
        System.out.println(formatted);
    }
}

Output:

06:45 fm

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • After Testing it on multiple devices I observed some strange behavior. It is working fine on all the devices except Samsung devices (On other device manufacturers it is working fine) – Shobhith Nov 21 '22 at 14:31
1

The Answer by Arvind Kumar Avinash is correct and smart.

In addition, we can let java.time automatically localize rather than hard-code a format.

Automatic localization

tl;dr

localTime
.format(
    DateTimeFormatter
    .ofLocalizedTime( FormatStyle.SHORT )
    .withLocale( new Locale( "sv" , "SE" ) )  // Swedish language, Sweden culture.
)

See this code run at Ideone.com.

06:45

Details

You appear to be interested in only the hour and minute, but not the second or fractional second. So we can truncate the value.

LocalTime localTime = localTime.truncatedTo( ChronoUnit.MINUTES ) ;

We can examine a few locales, for comparison. We will try Sweden, United States, and Canada (French).

List < Locale > locales = List.of( new Locale( "sv" , "SE" ) , Locale.US , Locale.CANADA_FRENCH );

Loop the locales. For each locale, loop the various FormatStyle enum object that can work with a time-of-day only value (SHORT & MEDIUM).

for ( Locale locale : locales )
{
    System.out.println( "-------|  " + locale + "  |--------" );
    for ( FormatStyle formatStyle : List.of( FormatStyle.SHORT , FormatStyle.MEDIUM ) )
    {
        DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedTime( formatStyle ).withLocale( locale );
        String output = localTimeTruncated.format( formatter );
        System.out.println( formatter + " ➠ " + output );
    }
}

When run:

localTime = 06:45:07
localTimeTruncated = 06:45
-------|  sv_SE  |--------
Localized(,SHORT) ➠ 06:45
Localized(,MEDIUM) ➠ 06:45:00
-------|  en_US  |--------
Localized(,SHORT) ➠ 6:45 AM
Localized(,MEDIUM) ➠ 6:45:00 AM
-------|  fr_CA  |--------
Localized(,SHORT) ➠ 06 h 45
Localized(,MEDIUM) ➠ 06 h 45 min 00 s
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154