3

I need to parse week day name into DayOfWeek. Week day name may be either in short ('Mon') or long ('Monday') format.

Currently I've come up with such solution:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE", locale);
DayOfWeek dayOfWeek;
try {
    dayOfWeek = DayOfWeek.from(dtf.parse(value));
}
catch (DateTimeException e) {
    dtf = DateTimeFormatter.ofPattern("EEEE", locale);
    dayOfWeek = DayOfWeek.from(dtf.parse(value));
}

Is there a shorter solution?

Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
Lega
  • 88
  • 8

2 Answers2

5

You can use DateTimeFormatterBuilder with optional patterns. These will be tried in the order you append them. A DateTimeException will still be thrown if all patterns fail.

final DateTimeFormatter dtf = new DateTimeFormatterBuilder()
        .appendOptional(DateTimeFormatter.ofPattern("EEEE"))
        .appendOptional(DateTimeFormatter.ofPattern("E"))
        .toFormatter(locale);

final DayOfWeek dow1 = DayOfWeek.from(dtf.parse("Mon"));
final DayOfWeek dow2 = DayOfWeek.from(dtf.parse("Monday"));

Note how the resulting DayOfWeek can now be final if you want.


Try that same code across multiple languages (multiple locales).

for ( final Locale locale : new Locale[] { Locale.US , Locale.CANADA_FRENCH , Locale.ITALY , Locale.KOREA } ) {
    final String inputShort = ( DayOfWeek.MONDAY.getDisplayName ( TextStyle.SHORT, locale ) );
    final String inputFull = ( DayOfWeek.MONDAY.getDisplayName ( TextStyle.FULL, locale ) );

    final DateTimeFormatter dtf = new DateTimeFormatterBuilder ( )
            .appendOptional ( DateTimeFormatter.ofPattern ( "EEEE" ) )
            .appendOptional ( DateTimeFormatter.ofPattern ( "E" ) )
            .toFormatter ( locale );

    final DayOfWeek dow1 = DayOfWeek.from ( dtf.parse ( inputShort ) ); 
    final DayOfWeek dow2 = DayOfWeek.from ( dtf.parse ( inputFull ) ); 

    System.out.println ( "" );
    System.out.println ( "Language: " + locale.getDisplayLanguage ( Locale.US ) );
    System.out.println ( "inputShort: " + inputShort + " | dow1: " + dow1 );
    System.out.println ( "inputFull: " + inputFull + " | dow2: " + dow2 );
}

When run.

Language: English
inputShort: Mon | dow1: MONDAY
inputFull: Monday | dow2: MONDAY

Language: French
inputShort: lun. | dow1: MONDAY
inputFull: lundi | dow2: MONDAY

Language: Italian
inputShort: lun | dow1: MONDAY
inputFull: lunedì | dow2: MONDAY

Locale: Korean
inputShort: 월 | dow1: MONDAY
inputFull: 월요일 | dow2: MONDAY
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
  • 1
    This is definitely a better answer. :) – Amir Raminfar Mar 23 '17 at 17:12
  • 2
    Thanks! Exactly what I was looking for! I think it would be better (shorter) to use ofPattern("E") etc. and toFormatter(locale) instead, in case more patterns are required – Lega Mar 23 '17 at 17:56
  • 1
    @Lega certainly! updated answer. It would be even better if they had `appendOptionalPattern` method with a `String` argument. Which I believe is what most people want. – Manos Nikolaidis Mar 23 '17 at 18:21
0

Don't use try-catch to do conditions. catch is slow. Conditions are better fit with if.

final static DateTimeFormatter shortDTF = DateTimeFormatter.ofPattern("EEE", locale);
final static DateTimeFormatter longDTF = DateTimeFormatter.ofPattern("EEEE", locale);

TemporalAccessor parsed; 
try{ 
 if(value.length() > 3){
   parsed = longDTF.parse(value)
 } else {
   parsed = shortDTF.parse(value)  
 }
 dayOfWeek = DayOfWeek.from(parsed);
} catch(DateTimeException e){
  // throw exception here 
}

If you performance test with 100,000 of parses, the if statement will be much faster.

Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
  • Also, don't worry about writing shorter code. Worry about writing easier to read, faster, and maintainable code. That's more important. – Amir Raminfar Mar 23 '17 at 15:50
  • 2
    Your Answer appears to be using the [Joda-Time](http://www.joda.org/joda-time/) library, as there is no `DateTime` class in java.time. The Question is aimed at java.time classes, the successor to Joda-Time. The [Joda-Time](http://www.joda.org/joda-time/) project, now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), advises migration to the [java.time](http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. – Basil Bourque Mar 23 '17 at 20:57
  • Fixed to use `TemporalAccessor`. – Amir Raminfar Mar 23 '17 at 21:26
  • 1
    The java.time framework recommends *against* using the interfaces. Per [`TemporalAccessor`](https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAccessor.html) doc: This interface is a framework-level interface that should not be widely used in application code. Instead, applications should create and pass around instances of concrete types, such as LocalDate. – Basil Bourque Mar 23 '17 at 21:36