0

I want to use the Java Time API to get the central Europen summer time (CEST) and format it correctly. I have the following code:

LocalDateTime localDateTime= LocalDateTime.now();
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
localDateTime.format(myFormatObj);
ZoneId europeBerlin = ZoneId.of("Europe/Berlin");
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, europeBerlin);

The command zonedDateTime.toString()leaves to the following output:

2020-09-27T08:42:33.660+02:00[Europe/Berlin]

But I would like to have an output as specified before in the DateTimeFormatter ("dd-MM-yyyy HH:mm:ss"). I have already formatted the localDateTime into this format and now I just want to get the CEST time. How can I do that? I'd appreciate every comment.

VanessaF
  • 515
  • 11
  • 36
  • 2
    If you want to use a zoned time, use `ZonedDateTime`. To convert it back to a `LocalDateTime` call [`ZonedDateTime::toLocalDateTime`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/time/ZonedDateTime.html#toLocalDateTime()). – Turing85 Sep 27 '20 at 09:01
  • Thanks Turing for your comment. For me it does not watter which class I am using. I just want to have the CEST time formatted in the way I specified in the code ("dd-MM-yyyy HH:mm:ss") – VanessaF Sep 27 '20 at 09:48
  • 1
    I used to work with SimpleDateFormat.I just read it is better to use the Java Time API. So I guess it will be good, if I can stick to the Java Time API and not use the ZonedTime if that is possible. But in generall I could also use the ZonedTime if it is better – VanessaF Sep 27 '20 at 09:52
  • Does this answer your question? [String to ZonedDateTime is changing format](https://stackoverflow.com/questions/50120213/string-to-zoneddatetime-is-changing-format) – Ole V.V. Sep 27 '20 at 10:13
  • 1
    Really all you need is `String formattedDateTime = zonedDateTime.format(myFormatObj);`. – Ole V.V. Sep 27 '20 at 10:15
  • Thanks Ole for your comment. Basically now the format is correct but the time itself is wrong. It is not the CEST time (but 2 hours earlier) – VanessaF Sep 27 '20 at 10:29
  • How can I get the correct time? It is kind of strange because I specify Berlin in the timezone but the result is not the correct time for Berlin – VanessaF Sep 27 '20 at 10:52

2 Answers2

2

Please note that date-time objects from the Java Time API are immutable. Therefore, whenevery you want to modify an existing date-time instance, a new fresh copy is returned, leaving the old one untouched.

Also, a minor optimization: DateTimeFormatter is thread-safe. Thus, there is no need to construct a new instance every time, since the format is constant. You could declare it at the top like this:

private static final DateTimeFormatter FORMATTER;

static {
    FORMATTER = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
}

To print a formatted String, use the following:

LocalDateTime localDateTime = LocalDateTime.now();
ZoneId europeBerlin = ZoneId.of("Europe/Berlin");
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, europeBerlin);

// please note that #format has a return value
// originally, you called 'localDateTime.format(myFormatObj);' while ignoring
// the return value
String formatted = FORMATTER.format(zonedDateTime);

System.out.println(formatted); // e.g. 27-09-2020 11:44:27

Edit 1: Regarding thread-safety Thread-safety refers to when an object can safely be used by mutliple threads concurrently, without breaking internals of the class. If a class is thread-safe, you can call it from mutliple threads at the same time (therefore you do not need to create a new instance every time, but only one). If a class is not thread-safe, a new instance is needed for each thread.

Glains
  • 2,773
  • 3
  • 16
  • 30
  • Thanks Glains for your answer. What do you mean by Thead-safe? And you are using a static initializer, right? I was told many times that I should avoid using something like this. – VanessaF Sep 27 '20 at 10:02
  • See my edit for thread safety. Regarding the static initializer: You can use an instance initializer as well. What is the reason you have been told to avoid those blocks? You can stick with your previous example as well to not make it too complicated, but i tought it is good to provide best-practises (also to new people learning Java, since i see a lot of code with these _inefficiencies_). – Glains Sep 27 '20 at 10:11
  • A very common example are usages of regular expressions, see [here](https://www.baeldung.com/java-regex-pre-compile) for more information if you are curious. – Glains Sep 27 '20 at 10:13
  • Thanks Glains for your answers and effort. Ole posted a very easy solution for the formatting: "String formattedDateTime = zonedDateTime.format(myFormatObj);" (see above). However, the timezone is not correct. But basically I'd like to stick to easy solutions. Your solution with the static initilatizer seems to be unnecessarily complex. But still thanks a lot for the answer. If I can't manage to fix the timezone problem with Ole's suggestion, I will use your answer. – VanessaF Sep 27 '20 at 10:37
  • A generall disadvantage of the Time API is that I get a warning in Android Studio telling me : " Call requires API level 26 (current min is 15): java.time.LocalDateTime#format ". You do not get this warning with SimpleDateFormat. So maybe I should use SimpleDateFormat such that also older Android versions can use my app. – VanessaF Sep 27 '20 at 10:38
  • Sure, and again some side note: `SimpleDateFormat` is **not** thread-safe, but you can create a `String` constant for the format. – Glains Sep 27 '20 at 10:43
  • Okay, I am now confused. As Android is using many threads does this mean that using the SimpleDateFormat will lead to erros when a Thread calls it? I just want to format the date and nothing more. This should not be difficult thing thought but now all options seem to be not good (either the risk of error when using simple date format or only new devices can use it when using the Time API) – VanessaF Sep 27 '20 at 10:47
  • Why do I need thread safety in my example? What will happen when I use the SimpleDateFormat? Further in SImpleDateFormat I also have the problem with the wrong time zone. The time is 2 hours to early and I do not know how to fix it. – VanessaF Sep 27 '20 at 10:49
0
    DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
    ZoneId europeBerlin = ZoneId.of("Europe/Berlin");
    ZonedDateTime zonedDateTime = ZonedDateTime.now(europeBerlin);
    
    String formattedDateTime = zonedDateTime.format(myFormatObj);
    System.out.println(formattedDateTime);

Output when running in UTC time zone just now:

27-09-2020 20:33:53

We got the Berlin time (not the UTC time).

What went wrong in your code?

Two things:

  1. LocalDateTime.now() gives you the current time in the default time zone of the JVM. It seems that this was not Eurpoe/Berlin (perhaps it was UTC, it could be something else). Then ZonedDateTime.of(localDateTime, europeBerlin) takes that date and time of day and claims that it is Europe/Berlin time zone, which is wrong and the reason why you got an incorrect result. You don’t often need the LocalDateTime class and virtually never the no-arg LocalDateTime.now() method.
  2. To get the time in a specific format you need to format the date and time into a string. The LocalDateTime and the ZonedDateTime objects haven’t got any format.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161