64

I want to convert a ZonedDateTime to a String in the format of ("dd/MM/yyyy - hh:mm"). I know this is possible in Joda-Time other types, just using their toString("dd/MM/yyyy - hh:mm")....But this doesn't work with ZonedDateTime.toString().

How can I format a ZonedDateTime to a String?


EDIT:

I tried to print the time in another timezone and the result appears to be the same always:

ZonedDateTime date = ZonedDateTime.now();
ZoneId la = ZoneId.of("America/Los_Angeles");
ZonedDateTime date2 = date.of(date.toLocalDateTime(), la);

// 24/02/2017 - 04:53
System.out.println(DateTimeFormatter.ofPattern("dd/MM/yyyy - hh:mm").format(date));
// same result as the previous one
// 24/02/2017 - 04:53
System.out.println(DateTimeFormatter.ofPattern("dd/MM/yyyy - hh:mm").format(date2));

And I am not in the same timezone as Los Angeles.


EDIT 2:

Found how to change the timezones:

// Change this:
ZonedDateTime date2 = date.of(date.toLocalDateTime(), la); // incorrect!
// To this:
ZonedDateTime date2 = date.withZoneSameInstant(la);
Community
  • 1
  • 1
Michel Feinstein
  • 13,416
  • 16
  • 91
  • 173

3 Answers3

105

You can use java.time.format.DateTimeFormatter. https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

Here there is an example

ZonedDateTime date = ZonedDateTime.now();

System.out.println(DateTimeFormatter.ofPattern("dd/MM/yyyy - hh:mm").format(date));
reos
  • 8,766
  • 6
  • 28
  • 34
3

The format dd/MM/yyyy - hh:mm does not make sense

The format dd/MM/yyyy - hh:mm does not make sense because of missing a which gives it a meaning. Note that h represents clock-hour-of-am-pm (1-12) and a represents am-pm-of-day i.e. without a, the hour returned by h will be ambiguous e.g. without a, h will not differentiate between 9:00 am and 9:00 pm.

Therefore, use H which represents hour-of-day (0-23) or use h with a.

Also, always use Locale with the formatter because Date-Time parsing/formatting API is Locale-sensitive.

ZoneId zoneId = ZoneId.of("Europe/London");
ZonedDateTime zdt9Am = ZonedDateTime.of(LocalDate.now(), LocalTime.of(9, 0), zoneId);
ZonedDateTime zdt9Pm = ZonedDateTime.of(LocalDate.now(), LocalTime.of(21, 0), zoneId);

DateTimeFormatter ambiguousFormatter = 
                    DateTimeFormatter.ofPattern("dd/MM/yyyy - hh:mm", Locale.ENGLISH);
String ambiguosDtStr1 = zdt9Am.format(ambiguousFormatter);
String ambiguosDtStr2 = zdt9Pm.format(ambiguousFormatter);
System.out.println(ambiguosDtStr1); // 08/10/2022 - 09:00
System.out.println(ambiguosDtStr2); // 08/10/2022 - 09:00

DateTimeFormatter correctAmPmFormatter = 
                    DateTimeFormatter.ofPattern("dd/MM/yyyy - hh:mm a", Locale.ENGLISH);
System.out.println(zdt9Am.format(correctAmPmFormatter)); // 08/10/2022 - 09:00 AM
System.out.println(zdt9Pm.format(correctAmPmFormatter)); // 08/10/2022 - 09:00 PM

DateTimeFormatter correct24HourFormatter = 
                    DateTimeFormatter.ofPattern("dd/MM/yyyy - HH:mm", Locale.ENGLISH);
System.out.println(zdt9Am.format(correct24HourFormatter)); // 08/10/2022 - 09:00
System.out.println(zdt9Pm.format(correct24HourFormatter)); // 08/10/2022 - 21:00

Check DateTimeFormatter documentation to learn more about it.

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
1

Many thanks for above. Here it is in scala where localDateTime.now always Zulu/UTC time.

import java.time.format.DateTimeFormatter
import java.time.LocalDateTime
import java.time.ZoneId

val ny = ZoneId.of("America/New_York")
val utc = ZoneId.of("UTC")
val dateTime = LocalDateTime.now.atZone(utc)

val nyTime = DateTimeFormatter.
      ofPattern("yyyy-MMM-dd HH:mm z").
      format(dateTime.withZoneSameInstant(ny))
Tony Fraser
  • 727
  • 7
  • 14