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 real device it is not working.
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.
CodePudding user response:
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.
CodePudding user response:
The Answer by Arvind Kumar Avinash is correct and smart.
Automatic localization
tl;dr
localTime
.format(
DateTimeFormatter
.ofLocalizedTime( FormatStyle.SHORT )
.withLocale( new Locale( "sv" , "SE" ) )
)
Details
In addition, we can let java.time automatically localize rather than hard-code a format.
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