Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Calendar.getInstance with specified Locale

Tags:

java

calendar

I am trying to use Calendar.getInstance(Locale l) with specified Locale and is not working. I cannot figure out what I am doing wrong.

The Java Doc. say:

getInstance public static Calendar getInstance(Locale aLocale) Gets a calendar using the default time zone and specified locale. The Calendar returned is based on the current time in the default time zone with the given locale. Parameters: aLocale - the locale for the week data Returns: a Calendar.

My code:

 public static void main (String[] args){

     Locale local = new Locale("pt", "BR");

     Calendar c = Calendar.getInstance(local); // here I am using the method
     System.out.println(c.getTime()); // and here, I cannot figure out why is not working


     DateFormat dt = DateFormat.getDateInstance(DateFormat.LONG, local);
     String s = dt.format(c.getTime());
     System.out.println(s); // here just a example in portuguese Brasil
 }

Output:

Wed Apr 29 10:18:16 BRT 2015

29 de Abril de 2015

Should the first print must be in Locale("pt", "BR"), in portuguese?

like image 270
G Bisconcini Avatar asked Feb 11 '23 07:02

G Bisconcini


2 Answers

The Answer by Loc is correct: Your call to Calendar::getTime produces a java.util.Date object. The java.util.Date class has no explicit time zone yet its toString method confusingly applies the JVM’s current default time zone while generating a String.

All very confusing names and behavior - some of the many reasons to avoid these poorly designed, confusing, and troublesome old legacy date-time classes. Instead you should be using the java.time classes that officially supplant the old classes.

java.time

Get the current moment in UTC. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.now();

You can create a String to represent that value with standard ISO 8601 formatting by calling toString.

String output = instant.toString();

2016-09-28T19:38:21Z

The code in the Question ignores the issue of time zone. When you do not specify a time zone your JVM’s current default time zone is implicitly applied. Better to specify explicitly.

Note that Locale and time zone are two completely separate distinct issues.

  • Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.
  • Time zone determines the wall-clock time used to present the date-time value.

You can have any combination of the two. For example, a time zone of Kolkata India with a French locale, or a Brazil Portuguese locale with an Auckland New Zealand time zone.

Locale locale = new Locale("pt", "BR");
ZoneId z = ZoneId.of( "Pacific/Auckland" );

Apply the time zone as a ZoneId to produce a ZonedDateTime. Conceptually, think of it as ZonedDateTime = ( Instant + ZoneID ).

Specify a proper time zone name in the format of continent/region. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZonedDateTime zdt = instant.atZone( z );

The Locale does not affect the meaning, on the presentation. We can let the Locale object drive the automatic localization of when producing a String to represent the date-time value via the DateTimeFormatter class. Specify a FormatStyle to determine how long or abbreviated should the string be.

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
                                       .withLocale( locale );
String output = zdt.format( f );

Dump to console. The instant and zdt objects seen here represent the very same moment, the same point on the timeline. The only difference is a view through the lens of a different region’s wall-clock time.

System.out.println ( "instant.toString(): " + instant 
                     + " | zdt: " + zdt 
                     + " | output: " + output );

instant.toString(): 2016-09-28T20:20:38.242Z | zdt: 2016-09-29T09:20:38.242+13:00[Pacific/Auckland] | output: Quinta-feira, 29 de Setembro de 2016 09h20min38s NZDT

Conversion

Avoid the old .Date and .Calendar classes. But if you must use them with old code not yet updated for the java.time types, you can convert. Use new methods added to the old classes. Here we call java.util.GregorianCalendar.from( ZonedDateTime ).

java.util.Calendar cal = java.util.GregorianCalendar.from( zdt ) ;

And, going the other direction:

ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime() ;

About java.time

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

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

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

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

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.

like image 76
Basil Bourque Avatar answered Feb 12 '23 20:02

Basil Bourque


Your first print is just print Date information & Java using Default locale for this print (English)

System.out.println(c.getTime());

This print will perform: c.getTime().toString() method, and this method using Default locale (ENGLISH) - You can take a look at Date.toString() source code to see Java using Default locale.

That is why the output is 'Wed Apr 29 10:18:16 BRT 2015'

If you want print output is in portuguese. You must go with Second print.

like image 23
Loc Avatar answered Feb 12 '23 20:02

Loc