3

Howto pass a localization to the new Java Time API?

In this simple example i try to print current week-of-the-year but the result is always wrong.

import java.text.*;
import java.time.*;
import java.time.format.*;
import java.util.*;

//wrong result
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy ww");
System.out.println(LocalDateTime.now(ZoneId.of("Europe/Berlin")).format(formatter));

//this works
System.out.println(new SimpleDateFormat("yyyy ww",Locale.GERMANY).format(new Date()));
Khinsu
  • 1,487
  • 11
  • 27
  • What is wrong about the result that you get? I get 2016 29 in both cases, (which is, as far as I can tell, correct). – david a. Jul 20 '16 at 12:08
  • There are two DateTimeFormatter.ofPattern methods. [One of them takes a Locale.](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ofPattern-java.lang.String-java.util.Locale-) – VGR Jul 20 '16 at 12:09
  • Try DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy ww",Locale.GERMANY); – Unknown Jul 20 '16 at 12:19
  • @davida. i got 30 (time api) and 29(util.date), my system locale isnt set to germany. – Khinsu Jul 20 '16 at 12:48
  • this worked ´DateTimeFormatter.ofPattern("yyyy ww",Locale.GERMANY);´ – Khinsu Jul 20 '16 at 12:48
  • 2
    What is the point of using LocalDateTime.now() if your pattern does not include time ? Could simply use LocalDate.now(). – Jean-François Savard Jul 20 '16 at 12:50
  • **Beware:** Your lowercase `yyyy` (for calendar-year) should be uppercase `YYYY` for week-based-year. See [my Answer](https://stackoverflow.com/a/49838733/642706) for details. – Basil Bourque Apr 15 '18 at 05:28

2 Answers2

3

Pass the Locale to ofPattern method of DateTimeFormatter

 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy ww",Locale.GERMANY);
 System.out.println(LocalDateTime.now().format(formatter));
Jean-François Savard
  • 20,626
  • 7
  • 49
  • 76
Unknown
  • 2,037
  • 3
  • 30
  • 47
  • 1
    **Bad format:** Shows week with calendar-year (`yyyy`) rather than week-based-year (`YYYY`). See [my Answer](https://stackoverflow.com/a/49838733/642706) for explanation and correct code. – Basil Bourque Apr 15 '18 at 05:20
  • It all depends on what OP has asked. He had accepted this answer, which means it has resolved his issue. Moreover there is a link of Java Doc which has more information. – Unknown Apr 15 '18 at 05:23
  • The answer from @BasilBourque offers a correct and more complete explanation. – Vanja D. Jan 13 '22 at 17:28
2

tl;dr

Use proper formatting pattern, case-sensitive: "YYYY ww".

LocalDate.now( ZoneId.of( "Europe/Berlin" ) )    // Get the current date (date-only value) as seen in the wall-clock time used by the people of a certain region (a time zone).
.format(                                         // Generate a string representing the week and week-based-year according to a particular locale’s definition of ‘week’.
    DateTimeFormatter.ofPattern( "YYYY ww" ).withLocale( Locale.GERMANY )
)

yyyy ww is invalid

The yyyy coding in java.time means calendar-year. Following that with ww for a week number of a standard ISO 8601 week-based year is misleading and nonsensical.

You should be combining week-number with week-based-year number rather than calendar-year number. The formatting code for that is uppercase YYYY. So you would want YYYY ww.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "YYYY ww" ) ;

Locale affects YYYY not yyyy

Since yyyy lowercase means calendar year, specifying a Locale has no effect. Use YYYY uppercase, as mentioned above, if you want the locale-defined week-based-year.

For more info, see the Question: Java Time's week-of-week-based-year pattern parsing with DateTimeFormatter

Locale locale = Locale.GERMANY ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "YYYY ww" ).withLocale( locale ) ;
LocalDate ld = LocalDate.now( ZoneId.of( "Europe/Berlin" ) ) ; // Or "Africa/Tunis", "Pacific/Auckland" etc. Time zone is unrelated (orthogonal) to locale.
String output = ld.format( f ) ;

Standard week

Perhaps you want the ISO 8601 standard definition of week rather than a locale-defined definition. This is where week # 1 contains the first Thursday of the calendar year, and starts on a Monday, for a total of 52 or 53 weeks per year.

ISO 8601 defines a standard format for week-based year & week. You may want to consider using the standard format rather than your custom format.

Standard format is yyyy-Www for the year-week, and yyyy-Www-d to also display the day-of-week number where 1-7 is Monday-Sunday. For example, 2012-W48-6 is 2012-12-01, a Saturday (day-of-week # 6).

The DateTimeFormatter class comes with a predefined format for this, DateTimeFormatter.ISO_WEEK_DATE.

String input = "2012-W48-6";
LocalDate ld = LocalDate.parse( input , DateTimeFormatter.ISO_WEEK_DATE );
System.out.println( ld );

2012-12-01

You can generate such a string.

String output = ld.format( DateTimeFormatter.ISO_WEEK_DATE );

2012-W48-6

If you want the entire week, without the day-of-week, just truncate the string.

String output = ld.format( DateTimeFormatter.ISO_WEEK_DATE ).substring( 0 , 8 ) ;

2012-W48

YearWeek

If you will be doing much of this work at all, I suggest adding the ThreeTen-Extra library to your project. That library offers many handy classes, one of which is YearWeek to represent the standard ISO 8601 week as a whole.

YearWeek yw = YearWeek.parse( "2012-W48" ) ;

Get the current week.

YearWeek yw = YearWeek.now( ZoneId.of( "Europe/Berlin" ) )     

yw.toString(): 2012-W48


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

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