1

I'm trying to format an input date in Java which looks like follows in the debugger.

result = {Date@13861} "2019-09-29"
 fastTime = 1569729600000
 cdate = {Gregorian$Date@13873} "2019-09-29T00:00:00.000-0400"

I need to convert it into: 2019-09-28 20:00:00.0.

My code:

DateTimeFormatter dateTimeformatter_Test = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

LocalDate tempDate = LocalDate.parse(date.toString(), DateTimeFormatter.ofPattern( "yyyy-MM-dd" , Locale.US ));

But the line below throws a runtime error saying: Unsupported field: HourOfDay

String result= tempDate.format(dateTimeformatter_Test);

What am I missing here please?

Thanks.

5
  • 1
    Please provide a minimal reproducible example that reproduces the exact error. We should be able to copy the code and run it ourselves without getting any other errors than the one you are asking about. Commented Mar 2, 2020 at 21:47
  • date.toString() is a bad idea as the format not specified and could change. It looks like you have a java.util.Date and java.util.Calendar. LocalDate also has no concept of time, so you'll need to provide some means to inject that (ie LocalDate to LocalDateTime :/) Commented Mar 2, 2020 at 22:35
  • 1
    I think you have the zone offset wrong, because 2019-09-29T00:00:00.000-0400 is same time as 2019-09-29 04:00:00 UTC, not 2019-09-28 20:00:00.0, so unless you're in time zone America/New_York and targeting time zone -08:00 (America/Anchorage), your values don't make sense. Commented Mar 2, 2020 at 22:52
  • I think that you don’t mean parse but format?! To parse is to convert a string to an internal form, in this case a date-time object. To format is the opposite conversion. Please be clear about which one of them you’re after? Commented Mar 3, 2020 at 3:03
  • Also what do you need that format for? Asking because it suspiciously looks like an SQL timestamp, and you shouldn’t pass a timestamp as a string to your SQL database. Pass an OffsetDateTme, an Instant or a LocalDateTime. Commented Mar 3, 2020 at 3:05

2 Answers 2

1

Your question is lacking time zone information, but here is one way to convert 2019-09-29 into 2019-09-28 20:00:00.0:

System.out.println(
        LocalDate.parse("2019-09-29")
        .atStartOfDay(ZoneOffset.UTC)
        .withZoneSameInstant(ZoneId.of("America/New_York"))
        .format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S")));

Output

2019-09-28 20:00:00.0

Here is an entirely different way, showing the values you saw in the debugger:

TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));

java.sql.Date result = java.sql.Date.valueOf("2019-09-29");
System.out.println("result = " + result);

long fastTime = result.getTime();
System.out.println("fastTime = " + fastTime);

System.out.println("cdate = " + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(result));

ZonedDateTime zdt = Instant.ofEpochMilli(fastTime).atZone(ZoneId.of("America/Anchorage"));
System.out.println("zdt = " + zdt.format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S")));

Output

result = 2019-09-29
fastTime = 1569729600000
cdate = 2019-09-29T00:00:00.000-0400
zdt = 2019-09-28 20:00:00.0
Sign up to request clarification or add additional context in comments.

Comments

0

If this is for a time stamp for your SQL database: don’t give your database a time stamp as a string. Give it a proper date-time object. Since JDBC 4.2 this means:

  • For an SQL timestamp with time zone (recommended for the vast majority of purposes) provide an OffsetDateTime; many drivers accept an Instant too.
  • For an SQL timestamp without time zone provide a LocalDateTime.

So for example:

    java.sql.Date inputDate = getFromSomewhere();
    OffsetDateTime dateTimeForDatabase = inputDate.toLocalDate()
            .atStartOfDay(ZoneOffset.UTC)
            .toOffsetDateTime();
    System.out.println(dateTimeForDatabase);

    PreparedStatement stmt = yourDatabaseConnection.prepareStatement(
            "insert into your_table(your_timestamp_col) values (?)");
    stmt.setObject(1, dateTimeForDatabase);
    int rowsInserted = stmt.executeUpdate();

Example output from the print statement in the middle:

2019-09-29T00:00Z

The Z means UTC, so this is the same point in time as the 2019-09-28 20:00:00.0 you asked for, assuming that your JVM’s time zone is some variant of North American Eastern Time (America/Toronto or America/New_York).

The object that you see in your debugger looks very much like a java.sql.Date object, so I have taken this type as my starting point. The java.sql.Date class is poorly designed, though, in fact a true hack on top of the already poorly designed java.util.Date class. It is also long outdated. So if you could get a modern type instead, for example a LocalDate, it would be advantageous.

What went wrong in your code?

A LocalDate is a date without time of day, for example 2019-09-29. You were trying to format one using the format pattern yyyy-MM-dd'T'HH:mm:ss.SSS'Z'. So you are asking to include the time of day in the result, but as I said, the LocalDate hasn’t got a time of day, so this does not make sense. The error message that you got was actually pretty precise:

Unsupported field: HourOfDay

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.