I need to get two ZonedDateTime instances representing the beginning and the end of the current week.
ZonedDateTime currentDateTime = ZonedDateTime.now(); ZonedDateTime startOfThisWeek = currentDateTime.with(DayOfWeek.MONDAY).truncatedTo(ChronoUnit.DAYS).plusMinutes(1); ZonedDateTime endOfThisWeek = startOfThisWeek.plusDays(6); DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd kk:mm"); String startweek = startOfThisWeek.format(df); String endweek = endOfThisWeek.format(df); System.out.println(startweek); System.out.println(endweek);
Output:
2018-06-18 24:01 2018-06-24 24:01
What does this string represent? Is it 1 minute after midnight, morning of 2018-06-18? If so, why is 24:01 a valid time? I thought it should be 00:01 in a 24 hour clock representation.
Edit: and is there a way to format this to show 00:01 instead without transforming the string into a new string?
For time patterns, use mm for two-digit minute and ss for two-digit second. The hh pattern generates the two-digit hour for a 12-hour clock (e.g., 6PM is "06") and HH generates the two-digit hour for a 24-hour clock (e.g., 6PM is "18").
ZonedDateTime is an immutable representation of a date-time with a time-zone. This class stores all date and time fields, to a precision of nanoseconds, and a time-zone, with a zone offset used to handle ambiguous local date-times.
now() now() method of a ZonedDateTime class used to obtain the current date-time from the system clock in the default time-zone. This method will return ZonedDateTime based on system clock with default time-zone to obtain the current date-time. The zone and offset will be set based on the time-zone in the clock.
A ZonedDateTime represents a date-time with a time offset and/or a time zone in the ISO-8601 calendar system. On its own, ZonedDateTime only supports specifying time offsets such as UTC or UTC+02:00 , plus the SYSTEM time zone ID.
kk
to HH
.2018-06-18 24:01
…becomes:
2018-06-18 00:01
Tip: When debugging, use the default standard ISO 8601 format in generating a String
.
ZonedDateTime.now( ZoneId.of( "Africa/Tunis" ) ) .truncatedTo( ChronoUnit.DAYS ) .with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) ) .toString()
2018-06-18T00:00+01:00[Africa/Tunis]
k
= 1-24 hour (actually, 24-23)The deleted Answer by Jorn Vernee was correct: You are using k
which is documented as representing the time-of-day using a 24-hour clock running from 1 to 24.
What is not so clear in the doc is that the first hour is counted as 24, rather than 0. So it might be better stated to say that the day runs from 24-23, that is, 24, 1, 2, 3, … , 22, 23
. The value 24
represents the first hour of the day, not the last.
Here is a simple example using time-of-day only to demonstrate this behavior.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "kk:mm" ); LocalTime lt = LocalTime.MIN; String output = lt.format( f ); System.out.println( lt.toString() ); // Standard ISO 8601 format, 00-24. System.out.println( output ); // `kk` format is 24, 1 , 2, … , 22 , 23.
00:00
24:00
Note that this kk
behavior of java.time where the entire first hour of the day is labeled 24
in unusual, non-standard, and not commonly used. See Wikipedia. Apparently, this style is used occasionally in some special contexts where business hours extend beyond midnight such as broadcasting.
As for what you expected…
it should be 00:01 in a 24 hour clock representation.
If you want 0-23, use "H", as documented.
First, look at the default ISO 8601 formatted output.
ZonedDateTime currentDateTime = ZonedDateTime.now(); ZonedDateTime startOfThisWeek = currentDateTime.with( DayOfWeek.MONDAY ).truncatedTo( ChronoUnit.DAYS ).plusMinutes( 1 ); ZonedDateTime endOfThisWeek = startOfThisWeek.plusDays( 6 ); System.out.println( startOfThisWeek ); System.out.println( endOfThisWeek );
2018-06-18T00:01-07:00[America/Los_Angeles]
2018-06-24T00:01-07:00[America/Los_Angeles]
Now, your custom format. Change your formatting pattern from kk
to HH
.
DateTimeFormatter df = DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm" ); String startweek = startOfThisWeek.format( df ); String endweek = endOfThisWeek.format( df ); System.out.println( startweek ); System.out.println( endweek );
2018-06-18 00:01
2018-06-24 00:01
Some other notes…
If you are trying to represent the week, there is no need to add a minute. The generally best practice in representing a span-of-time is the Half-Open approach where the beginning is inclusive while the ending is exclusive. So a week starts at the first moment of one Monday and runs up to, but does not include, the first moment of the following Monday.
Also, I recommend always passing a ZoneId
explicitly to now
even if that be ZoneId.systemDefault
to make your intentions crystal-clear.
Adjusting to Monday has the issue of what to do if today is already a Monday. Use either of this pair of TemporalAdjuster
implementations found in TemporalAdjusters
to specify your choice of behavior:
previous( DayOfWeek )
previousOrSame( DayOfWeek )
Example code.
ZonedDateTime now = ZonedDateTime.now( ZoneId.of( "Africa/Tunis" ) ) ; // Or `ZoneId.systemDefault()`. ZonedDateTime weekStart = now.truncatedTo( ChronoUnit.DAYS ).with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) ); ZonedDateTime weekStop = weekStart.plusWeeks( 1L ) ;
For tracing and debugging, always generate a String representing the value of your date-time objects using standard ISO 8601 format rather than a custom format as seen your Question. The java.time classes use the standard formats by default in their toString
methods.
String outputStart = weekStart.toString() ; String outputStop = weekStop.toString() ;
2018-06-18T00:00+01:00[Africa/Tunis]
2018-06-25T00:00+01:00[Africa/Tunis]
If you want date-only values, use the LocalDateTime
.
You can represent your time range in a single object using the LocalDateRange
or Interval
classes found in the ThreeTen-Extra project.
Last tip: Let java.time do the heavy-lifting by using DateTimeFormatter.ofLocalized…
methods to automatically localize the generated strings using a specified Locale
to determine the human language and cultural norms of formatting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With