Home > OS >  Converting Date String to ZonedDateTime
Converting Date String to ZonedDateTime

Time:03-09

I'm receiving a query parameter date, as yyyy-MM-DD (2022-03-08).
I want to conver this to java.util.Calendar / java.util.GregorianCalendar formmat.

So my idea is converto: String -> ZonedDateTime -> Calendar.

What I did:

ZonedDateTime parsedDate = ZonedDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
//date = 2022-03-08

even with the correct format, I'm getting:

Text '2022-03-08' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {},ISO resolved to 2022-03-08 of type java.time.format.Parsed

I found out that this error occurs because my string does not have a TimeZone.

One suggestion was to use LocalDate

 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
 LocalDate date = LocalDate.parse(fecha, formatter);

but I can't use localDate as an argument for ZonedDateTime.parse().

What else could I try?

CodePudding user response:

I want to conver this to java.util.Calendar / java.util.GregorianCalendar formmat.

That seems silly; Calendar/GregorianCalendar is obsolete, and the API is horrendous. Why use a broken screwdriver when there's a shiny new one right there in the toolbox? Don't do this.

So my idea is converto: String -> ZonedDateTime -> Calendar.

That seems silly. The string does not contain a ZonedDateTime. It doesn't even contain a LocalDateTime. It is clearly a LocalDate. So, convert it to a localdate, and you go from there.

The power of the java.time package is that each different concept in time has a matching type in the j.t package that is properly named. For example, java.util.Date is a lie: It is a timestamp, and it has nothing whatsoever to do with dates; asking a Date object for 'what year is it', is broken (try it, you get a warning).

Calendar, similarly, is an utter falsehood. It does not represent a calendar at all; it, too, represents a timestamp.

LocalDate on the other hand is perfect truth: It represents a date (not a time), and it does not include timezone or other localizing information: It makes sense only as 'locally'.

Each stop should just make sense, on its own:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd");
LocalDate date = LocalDate.parse("2022-10-01", formatter);

So far, so good. I'd just stop there - why lie? Why return a Calendar which is both API wise a lie (that class does not represent calendars), and even if someone knows exactly what Calendar is, it's still a lie: A calendar implies it has exact time and a timezone. You do not have a time, and also don't have a timezone. Why return something that suggests stuff that isn't there?

But, if you MUST, then explicitly add a timezone and a time, and THEN go for it:

ZonedDateTime zdt = someLocalDate.atStartOfDay().atZone(ZoneId.of("Europe/Amsterdam"));
GregorianCalendar gc = GregorianCalendar.from(zdt);

This code is clear and legible: It makes crystal clear that the code picks a time, and picks a zone.

But, again, now you ended up with a horrible, horrible object you should not be using, for anything.

CodePudding user response:

There are other ways of getting a ZonedDateTime than just its static parse() method. Here's how to turn a LocalDateTime into a ZonedDateTime:

ZonedDateTime zoned = dateTime.atZone(ZoneId.of( "America/New_York"));

or if you have a LocalDate:

ZonedDateTime zoned = 
          date.atStartOfDay( ZoneId.of( "America/New_York" ));

I would not use java.util.Calendar or Date. They're junk. I'd either stick with LocalDate or use ZonedDateTime depending on if you need to keep track of time zones or not. This should get you where you want to go either way, I guess, as it sounds like you know what you want to do once you have a ZonedDateTime.

UPDATE: I looked up how to convert a ZoneDateTime to a Calendar:

Calendar calendar = GregorianCalendar.from(zoned);

just in case you hadn't gotten that far and really want to go that way.

CodePudding user response:

Here's some code which would work - you don't need to specify a formatter but I guess you could use the formatter if you really wanted to :)

import java.time.LocalDate;
LocalDate parsed = LocalDate.parse("2022-03-08");
System.out.println(parsed);

import java.util.Calendar;

Calendar c = Calendar.getInstance();
// Need to subtract 1 from month value since it is 1-based and Calendar month is 0-based
c.set(parsed.getYear(), parsed.getMonthValue() - 1, parsed.getDayOfMonth());

System.out.println(c);

But why do you want to use the java.util.Calendar API? This is considered legacy. java.time.* APIs are preferred.

  • Related