Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
392 views
in Technique[技术] by (71.8m points)

How to format a date by any locale obtained from language tag with java time?

I want to get a date as string and a language tag and based on that to parse the string by the locale format.

This is what I've done so far:

public static String formatDateByLocale(String date, String languageTag) {
    Locale locale = Locale.forLanguageTag(languageTag);
    String datePattern = DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.LONG, FormatStyle.LONG, Chronology.ofLocale(locale), locale);

    DateTimeFormatter targetFormat = DateTimeFormatter.ofPattern(datePattern).withLocale(locale);
    DateTimeFormatter currentFormat = DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm a");

    LocalDateTime localDateTime = LocalDateTime.parse(date, currentFormat);

    String result = targetFormat.format(localDateTime);


    return result;
}

This throws Unable to extract value: class java.time.LocalDateTime

How should I approach this to have this date: 17/04/2017 10:50AM with FR tag transform into 2017/04/17 10:50AM?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your example is incomplete and incorrect. You should provide a MCVE. Your example output of 17/04/2017 10:50AM is not at all close to the actual output of French with format style LONG. So we cannot answer precisely. But here is something to point you in the right direction.

You cannot count on being able to parse any date-time input string. Some ambiguities are impossible to resolve. And some crucial information such as offset-from-UTC or time zone may be omitted. Instead:

  • Within your app, pass around java.time objects, rather than mere strings.
  • Between apps/systems, pass strings is standard ISO 8601 format. Do so in UTC for date-time values, generally speaking.

Here is some example code showing your desired French output.

Capture the current moment in UTC as an Instant.

Instant instant = Instant.now( );

Adjust into a particular time zone. Remember that time zone has nothing to do with localization issues.

ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = instant.atZone( z );

Determine a Locale. Here we use French language with cultural norms of France.

Locale locale = Locale.forLanguageTag( "fr-FR" );

Your Question shows swapping of Chronology where appropriate for a locale. Has no effect here as both Instant and France use IsoChronology.

Chronology c = Chronology.ofLocale( locale );

Define a formatter. No need for the builder pattern seen in the Question.

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.SHORT ).withLocale( locale ).withChronology( c ) ;

Generate output.

String s = zdt.format( f );

Dump to console.

System.out.println( "instant.toString(): " + instant + " at zone: " + z + " in chrono: " + c + " = " + s );

instant.toString(): 2017-11-23T04:30:45.091424Z at zone: Asia/Kolkata in chrono: ISO = 23/11/2017 10:00

Note how this output cannot be parsed back into a date-time value as it lacks crucial information.

You could, in this case, parse the string to a LocalDateTime as shown in your Question. But you have data loss here. A LocalDateTime purposely has no concept of offset or zone, and so it does not represent a point on the timeline. A LocalDateTime is not an actual moment, only a vague hint of a range of possible moments that may be occurring over a period of about 26-27 hours. You are not even close to ending up where you started.

LocalDateTime ldt = LocalDateTime.parse( s , f );
System.out.println( "ldt: " + ldt );

ldt.toString(): 2017-11-23T10:00

By the way, I suggest your method take a Locale rather than a mere string of the language tag. The calling programmer should be responsible for determining the full Locale for a valid language tag. Language tags and their variants are complicated business. The calling programmer should verify they have properly defined a valid language construct by successfully instantiating a Locale (and, ideally, testing it). The method at hand here should focus on date-time issues and not have to also deal with language tag complications.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...