3

I'm trying to parse a Finnish date using the examples I've found here on Stack Overflow but I keep getting a parsing exception.

Here's my snippet:

SimpleDateFormat dftFormat = new SimpleDateFormat("dd MMMM yyyy", new Locale("fi", "FI"));
Date datDate = dftFormat.parse("25 syyskuu 2012");

The DateFormat characters seem to the same as the one in English so i'm wondering why this doesn't work.

Here's the information about the Finnish locale.

Thanks.

Mridang Agarwalla
  • 43,201
  • 71
  • 221
  • 382
  • 1
    That code works for me... what JRE are you using? – Jon Skeet Sep 25 '12 at 07:00
  • 1
    Not getting any exception. In sysout it prints `Tue Sep 25 00:00:00 IST 2012` – Subhrajyoti Majumder Sep 25 '12 at 07:01
  • I'm developing an Android app. I think I have bot JDK 1.6 and JDK1.7 installed but if remember correctly, Android used the 1.6. – Mridang Agarwalla Sep 25 '12 at 07:14
  • Here's my actual exception: `java.text.ParseException: Unparseable date: "25 syyskuu 2012" (at offset 3)`. – Mridang Agarwalla Sep 25 '12 at 07:16
  • 2
    Have you tried it the other way round? To output a date in the Finnish locale? Mybe it's an issue with the locale not being available? (Wild guess) – Fildor Sep 25 '12 at 07:21
  • Finnish locale is (at least officially) supported since Android 2.3, maybe you're using a previous version? See supported ones [here](http://colincooper.net/blog/2011/02/17/android-supported-language-and-locales/) – eis Sep 25 '12 at 07:25
  • My minimum SDK version is a set to AP113. I'm targeting only devices above 4.0.3 in which case it should be supported. – Mridang Agarwalla Sep 25 '12 at 07:50
  • 1
    Ok, try the thing suggested by @Fildor then - try the other way around and update to question what happens. – eis Sep 25 '12 at 08:27
  • @eis, I tried what you and @Fildor suggested and it worked. I was able to print out the date in the correct format. I even managed to parse the date. it seems that all Finnish dates end with a `ta` i.e. `syyskuu` becomes `syyskuuta`. The locale reference that I gave was wrong. If you see that link, you'll notice that the `ta` is missing. – Mridang Agarwalla Sep 26 '12 at 14:11
  • 1
    @MridangAgarwalla he, I'm actually Finnish myself, and still didn't think of that one. Glad it worked. "syyskuuta" would literally translate to "of September". Outside java world the date is actually written "25. syyskuuta", without the dot it has a different meaning... oh, well. – eis Sep 26 '12 at 14:26

2 Answers2

3

It seems that all Finnish dates end with a ta i.e. syyskuu becomes syyskuuta.

The locale reference that I gave was wrong. If you see that link, you'll notice that the ta is missing and that was some misleading information. I couldn't find the exact locale information for the Finnish locale in the Javadocs.

I learnt a lesson, thanks to @Eis and @Fildor, print out the date using your parsing format to see what the resultant string is. Then you can compare whether your input string is parseable using the format.

Here's how I tested my code:

Date datDate = dftFormat.parse("25 syyskuuta 2012");
System.out.println(new SimpleDateFormat("dd MMMM yyyy").format(datDate));
Mridang Agarwalla
  • 43,201
  • 71
  • 221
  • 382
2

tl;dr

Both syyskuu and syyskuuta are correct spellings of September in Finnish. The first is for standalone use, the second for use in context.

The java.time.Month enum can provide either form of spelling.

java.time

I tried this same kind of code using the modern java.time classes rather than the old outmoded java.util.Date and java.text.SimpleDateFormat classes.

The java.time framework built into Java 8 and later. See Oracle Tutorial. Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

Formatted String of date value

For this example we instantiate a LocalDate for September 25, 2012 per the Question.

LocalDate ld = LocalDate.of ( 2012 , Month.SEPTEMBER , 25 );  // 2012-09-25

We get a DateTimeFormatter to automatically localize when generating a String. Calling ofLocalizedDate means our String will represent only the date portion of the date-time value. The FormatStyle controls the length of the String (full, long, medium, short).

DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate ( FormatStyle.LONG );

Next we replace the assignment of our JVM’s current default Locale with the Finland & Finnish locale. This Locale object determines two things: (a) the human language used to translate pieces such as name of day or name of month, and (b) the cultural norms for abbreviating, ordering elements such as month or date first, use of commas versus periods, and so on.

Locale locale = new Locale ( "fi" , "FI" );
formatter = formatter.withLocale ( locale );

Use that formatter to actually generate a String to represent our LocalDate value.

String output = ld.format ( formatter );  // 25. syyskuuta 2012

Dump to console.

System.out.println ( "ld: " + ld + " with locale: " + locale + " | output: " + output );
  1. syyskuuta 2012

As shown in the accepted Answer, java.time agrees that syyskuuta is the name of the month for September.

Month name for display

The java.time classes include the Month enum. This handy class has a feature for generating a String with the name of the month localized to a Locale.

This localization is a similar to idea to the localization we saw in code above. But what is different is the use of a different enum to control the length of the text. Here the TextStyle enum (rather than FormatStyle) offers full, narrow, and short… but also “standalone” versions of those three lengths. In some languages there is a difference in the word used when the text is used alone, as opposed to in a complete date. Just for fun, let's try that with Finnish.

Locale locale = new Locale ( "fi" , "FI" );
EnumSet<TextStyle> styles = EnumSet.allOf ( TextStyle.class );

for ( TextStyle style : styles ) {
    System.out.println ( style + " | " + Month.SEPTEMBER.getDisplayName ( style , locale ) );
}

Mystery solved: Standalone month name

Sure enough, the output below explains the mystery. In Finnish:

  • When using the month name alone, drop the ta for syyskuu.
  • When used within the context of a specific date-time value include the ta for syyskuuta.

FULL | syyskuuta

FULL_STANDALONE | syyskuu

SHORT | syyskuuta

SHORT_STANDALONE | syys

NARROW | S

NARROW_STANDALONE | S

If you cannot control the improperly formatted inputs to your app, you could search-and-replace any standalone value with its proper version. Or perhaps you could use DateTimeFormatterBuilder to expect the standalone version (I do not know if this is possible, just a thought).

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154