Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hours not coming through when using LocalDate in Java

Tags:

java

java-time

I'm trying to format today's date to be "MM/dd/yyy HH:00" where the minutes are always zeroed out. The hours aren't coming through properly when using this format:

LocalDate date = DateTime.now().withZone(DateTimeZone.forID("America/New_York")).toLocalDate();
String format = date.toString("MM/dd/yyyy HH:00");

logger.info(format);

Output

enter image description here

Is there a different way to grab hours using LocalDate?

like image 842
PT_C Avatar asked Mar 12 '23 16:03

PT_C


2 Answers

From the JavaDoc for LocalDate:

A date without a time-zone in the ISO-8601 calendar system, such as 2007-12-03.

and:

This class does not store or represent a time or time-zone. Instead, it is a description of the date, as used for birthdays. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.

Use LocalDateTime instead.

like image 75
rmuller Avatar answered Mar 15 '23 06:03

rmuller


tl;dr

ZonedDateTime.now( ZoneId.of( "America/New_York" ) )
         .truncatedTo( java.time.temporal.ChronoUnit.HOURS )
         .format( DateTimeFormatter.ofPattern( "MM/dd/uuuu HH:mm" , Locale.US ) )

02/27/2017 23:00

Details

The Answer by rmuller is correct.

java.time vs Joda-Time

A bigger problem: You seem to be using Joda-Time classes but labeled your question with java-time meaning the java.time classes.

Meno Hochschild commented on the Question pointing out this apparent confusion of libraries.

The Joda-Time project is a separate library, not built into Java. This project provided the inspiration and experience for java.time. While similar in concepts, java.time is entirely re-engineered, not at all a drop-in replacement. Both Joda-Time and java.time are led by the same man, Stephen Colebourne (“jodastephen”). The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.

There are no DateTime or DateTimeZone classes in java.time.

Using java.time

In java.time, you code would be like this.

ZoneId z = ZoneId.of( "America/New_York" ) ;
LocalDate localDate = LocalDate.now( z ) ;

But you want a time-of-day, and as rmuller pointed out, you need to use another class as LocalDate is date-only without any time-of-day. Instead use ZonedDateTime to get the date and the time-of-day as seen through a particular region’s wall-clock time determined by a ZoneId.

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

Misuse of formatting pattern

Another problem: Hard-coding the formatting pattern to show zeros in place of minute-of-hour is a tricky way to accomplish your goal. Doing so does not make your intentions clear. Other programmers reading your code may miss your maneuver.

I find code to be more maintainable if it “tells the truth”. So rather than “lie” by altering the display of the minutes with hard-coded zero digits, it is better to alter the underlying data itself. Benefits include making your intentions clear, and making values seen in the debugger match the output of your strings.

truncatedTo

I suggest you instead alter the value of your date-time object explicitly. Call the truncatedTo method to lop off the minutes and seconds and fractional second. Those lopped-off values become zero.

The java.time use immutable objects. So rather than change the values (“mutate”) of an object, we generate a fresh object with values based on those of the original object.

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
ZonedDateTime zdtTruncatedToHour = zdt.truncatedTo( java.time.temporal.ChronoUnit.HOURS ) ;

zdtTruncatedToHour.toString(): 2017-02-27T23:00-05:00[America/New_York]

From there, you can use the usual toString or DateTimeFormatter ways to generate a string, with only zeros appearing in the minutes, seconds, and fractional second.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu HH:mm" , Locale.US );
String output = zdtTruncatedToHour.format( f );

02/27/2017 23:00

See this example code running live in IdeOne.com.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

  • Java SE 8 and SE 9 and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
    • See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

like image 32
Basil Bourque Avatar answered Mar 15 '23 07:03

Basil Bourque