24

The LocalDateTime API gives the possibility to add the TimeZone Name by using the key "z" in the formatter. I get an exception adding this key and don't understand why. I'm looking for something like this example '11:59:22 PM GMT' and not '**... UMT+2**'.

My Code:

public class TimeZone
{
    public static void main(String[] args)
    {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm:ss a z");
        System.out.println(now.format(formatter));
    }
}

The Exception:

Exception in thread "main" java.time.DateTimeException: Unable to extract value: class java.time.LocalDateTime
at java.time.format.DateTimePrintContext.getValue(Unknown Source)
at java.time.format.DateTimeFormatterBuilder$ZoneTextPrinterParser.format(Unknown Source)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(Unknown Source)
at java.time.format.DateTimeFormatter.formatTo(Unknown Source)
at java.time.format.DateTimeFormatter.format(Unknown Source)
at java.time.LocalDateTime.format(Unknown Source)
at tz.TimeZone.main(TimeZone.java:12)

Here is the DateTimeFormatter API part:

All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The following pattern letters are defined: 
  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   G       era                         text              AD; Anno Domini; A
   u       year                        year              2004; 04
   y       year-of-era                 year              2004; 04
   D       day-of-year                 number            189
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
   Y       week-based-year             year              1996; 96
   w       week-of-week-based-year     number            27
   W       week-of-month               number            4
   E       day-of-week                 text              Tue; Tuesday; T
   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
   F       week-of-month               number            3

   a       am-pm-of-day                text              PM
   h       clock-hour-of-am-pm (1-12)  number            12
   K       hour-of-am-pm (0-11)        number            0
   k       clock-hour-of-am-pm (1-24)  number            0

   H       hour-of-day (0-23)          number            0
   m       minute-of-hour              number            30
   s       second-of-minute            number            55
   S       fraction-of-second          fraction          978
   A       milli-of-day                number            1234
   n       nano-of-second              number            987654321
   N       nano-of-day                 number            1234000000

   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
   z       time-zone name              zone-name         Pacific Standard Time; PST
   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

Can anyone see what the problem is?

1
  • 1
    Some find the “local” in the class names LocalDate, LocalTime and LocalDateTime confusing. It means “without time zone”. If you want a date-time object that “knows” in which time zone it is local, use ZonedDateTime. Commented Mar 24, 2018 at 5:14

2 Answers 2

26

LocalDateTime has two fields of type LocalDate and LocalTime.
LocalDate has fields day, month, and year.
LocalTime has fields hour, minute, second, and nano.

Nowhere in that is a time zone given. Which is by nature, since the javadoc of LocalDateTime says:

A date-time without a time-zone

So, if the "local" date/time value is already representing a time in UTC, and you want it formatted saying so, you have multiple options:

  • Change the LocalDateTime to a ZonedDateTime by calling atZone():

    System.out.println(time.atZone(ZoneOffset.UTC)
                           .format(DateTimeFormatter.ofPattern("hh:mm:ss a z")));
    
  • Specify an override time zone in the formatter by calling withZone():

    System.out.println(time.format(DateTimeFormatter.ofPattern("hh:mm:ss a z")
                                                    .withZone(ZoneOffset.UTC)));
    
  • Format with a literal Z character:

    System.out.println(time.format(DateTimeFormatter.ofPattern("hh:mm:ss a 'Z'")));
    

All three of the above outputs:

11:59:22 PM Z


Now, if the "local" date/time is really in a different time zone, you can use either of the first two, and just specify the actual zone.

E.g. if time zone is -04:00, use ZoneOffset.ofHours(-4), and you'll get:

11:59:22 PM -04:00

Or if you are in New York, use ZoneId.of("America/New_York"), and you'll get:

11:59:22 PM EDT

If the "local" date/time is for New York, but you want formatted text to be UTC, use both at the same time, i.e.

System.out.println(time.atZone(ZoneId.of("America/New_York"))
                       .format(DateTimeFormatter.ofPattern("hh:mm:ss a z")
                                                .withZone(ZoneOffset.UTC)));

With that, you get the time converted to:

03:59:22 AM Z

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your extensive answer. I ll try your solutions! That question seems to bring up the question of how the computer actually gets it's numbers for the time. So if i want to show a different time zone from my locale I have to manually calculate the offset?
@Herr.Roehrig If you want current time in New York, regardless of what your default time zone is, call LocalDateTime.now(ZoneId.of("America/New_York")). So if you learned anything from my answer, you'd figure out that getting current time in UTC, you do LocalDateTime.now(ZoneId.of(ZoneOffset.UTC)).
@Herr.Roehrig Talking about LocalDateTime.now(): Since you called the no-arg overload of now(), the time is in the default time zone, i.e. in the ZoneId.systemDefault() time zone, so that is the time zone you'd want to specify in the code in the answer.
Caution: 'Z' is not the same as Z which means one can use the 3rd option of this answer only when the required time zone is UTC.
8

The LocalDateTime class does not support time zones; you can use ZonedDateTime instead.

ZonedDateTime now = ZonedDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm:ss a z");
System.out.println(now.format(formatter));

This no longer throws an exception and prints 06:08:20 PM EDT for me, but the timezone will differ depending on your location.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.