shaoyibai
shaoyibai

Reputation: 55

Joda-Time parse datetime in different language

I am trying to parse time with Joda-Time using similar code as below (copied from btiernay in Using Joda Date & Time API to parse multiple formats)

DateTimeParser[] parsers = { 
        DateTimeFormat.forPattern( "yyyy-MM-dd HH" ).getParser(),
        DateTimeFormat.forPattern( "yyyy-MM-dd" ).getParser() };
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append( null, parser).toFormatter();

DateTime date1 = formatter.parseDateTime( "2010-01-01" );
DateTime date2 = formatter.parseDateTime( "2010-01-01 01" );

however, the application maybe used overseas, which means the month may contain foreign language,

For example Haz is shorten for June in Turkish, how do I make it parse "07.Haz.2014", It throws an java.lang.IllegalArgumentException: Invalid format

Upvotes: 3

Views: 5840

Answers (1)

Basil Bourque
Basil Bourque

Reputation: 339332

Format Must Match Your Inputs

Your input data 07.Haz.2014 does not match the format in your example code, yyyy-MM-dd HH.

See the example code below for correct format pattern.

Specify a Locale

To parse the names of Turkish months, you must specify a Java locale (which includes a language). See this question, Setting Turkish and English locale.

Example code in Joda-Time 2.3.

A Locale object consists of a language and a country/region.

Note the use of a time zone. If you omit the time zone, one will be assigned for you, the JVM's current default time zone. Better to specify one rather than depend on default. The time zone controls how to interpret the beginning of the day. June 7th begins at different moments around the world, with a new day dawning earlier in Istanbul than it does Montréal for example.

Do not confuse locale and time zone.

  • Locale = Language + Culture
    • The locale controls the language used for choosing names of months, day-of-week, and such when parsing/generating text.
    • The country/region portion of a Locale does not adjust the time to that area. Rather, the country/region defines the cultural rules applied when generating a textual representation of a date-time. For example, should the day-of-week be placed at the front.  
  • Time Zone = Offset + Anomalies
    • The time zone adjusts to the local wall-clock time. A time zone represents some number of hours and minutes ahead or behind UTC. This offset is represented by PLUS or MINUS with double-digit hours, and optionally double-digit minutes. Examples: -08:00 for west coast of North America being several hours behind UTC, and +05:30 for India being five and half hours ahead of UTC.
    • A time zone also encapsulates the past, present, and planned anomalies such as historical corrections, political/bureaucratic adjustments, and Daylight Saving Time nonsense.

Generally we think of locale and time zone together, with a time zone used in the geography of a locale, but actually they can be orthogonal. For example, a businessperson in Montréal may want to read in French the date-time string that represents the local date-time when a Turkish customer is expecting a delivery. In such a case, the string is rendered with a Québécois locale but a Turkish time zone.

I strongly recommend always specifying both the locale and the time zone. If omitted, the JVM's default for either/both is applied. This application of a default causes no end of confusion in date-time programming.

String input = "07.Haz.2014";

java.util.Locale locale = new java.util.Locale( "tr", "TR" );
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Istanbul" );  // Assuming this time zone (not specified in Question).
DateTimeFormatter formatter = DateTimeFormat.forPattern( "dd.MMM.yyyy" ).withLocale( locale ).withZone( timeZone );
DateTime dateTime = formatter.parseDateTime( input );
String outputQuébécois = DateTimeFormat.forStyle( "FF" ).withLocale( java.util.Locale.CANADA_FRENCH ).print( dateTime ); // 
DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );

Dump to console…

System.out.println( "input: " + input );
System.out.println( "locale: " + locale );
System.out.println( "dateTime: " + dateTime );
System.out.println( "outputQuébécois: " + outputQuébécois );
System.out.println( "dateTimeUtc: " + dateTimeUtc );

When run…

input: 07.Haz.2014
locale: tr_TR
dateTime: 2014-06-07T00:00:00.000+03:00
outputQuébécois: samedi 7 juin 2014 0 h 00 EEST
dateTimeUtc: 2014-06-06T21:00:00.000Z

Upvotes: 12

Related Questions