I need to do a LocalDateTime conversion of a UTC date to another LocalDateTime variable considering a specific timezone tz.
During my research I found many solutions, but they all convert the LocalDateTime to another type, like ZonedDateTime.
I need something like that, but LocalDateTime wont work with ZoneId:
LocalDateTime output = input.getInitDate().of(ZoneId.of(tz))
Considering a -3 timezone:
input: 2019-12-03T18:24:07
output: 2019-12-03T15:24:07
Your Question makes no sense.
You need to understand that LocalDateTime holds nothing but a date and a time-of-day. The class purposely lacks any concept of time zone or offset-from-UTC. So LocalDateTime does not represent a moment. The name can be misleading, as a LocalDateTime is not about any particular locality.
If you want to track a moment in UTC, use Instant.
Instant instant = Instant.now() ; // Capture the current moment in UTC. Always in UTC, by definition.
If you want to track a moment as seen in the wall-clock time used by the people of a particular region (a time zone), use ZonedDateTime.
ZoneId z = ZoneId.of( "America/Montevideo" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
LocalDateTime conversion of a UTC date
Do you mean you have particular date and time in mind as seen at the prime meridian? Or as seen in Iceland which uses UTC as their time zone?
LocalDate ld = LocalDate.of( 2020 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 15 , 0 ) ; // 3 PM.
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ;
This ldt object means "3 PM on the 23rd of January this year" somewhere, or anywhere. But that LocalDateTime object does not 3 PM in one particular place. We have no idea if the intention here is 3 PM in Tokyo Japan or 3 PM in Toulouse France or 3 PM in Toledo Ohio US. Those would be three different moments, several hours apart. A LocalDateTime represents none of them, or all of them, whichever way you want to see it, but not any one of them.
To determine a moment from a date and a time-of-day, you need the context of a time zone or offset-from-UTC. In other words the third piece of information, in addition to the date and the time-of-day, we need is "as seen in Paris France" or "as seen in Palmer Station in Antarctica". With such a context, we get either ZonedDateTime or OffsetDateTime, respectively.
ZoneId z = ZoneId.of( "Antarctica/Palmer" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ldt , z ) ; // Giving context of time zone to the date-with-time `LocalDateTime` object. Determines a moment.
To see that same moment in UTC (an offset of zero hours-minutes-seconds), extract an Instant.
Instant instant = zdt.toInstant() ; // Adjust from time zone to UTC.
Time zone versus offset-from-UTC
Considering a -3 timezone:
No, -3 is not a time zone, it is an offset.
The -3 is short for -03:00. Practically speaking, I suggest you avoid abbreviating the offset as some libraries expect a full hours-with-minutes including the colon character, and including the leading zero on single-digit hours or minutes.
The -3 or -03:00 means simply "three hours behind UTC".
A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. A time zone has a name in the form of Continent/Region such as Africa/Tunis or Europe/Paris.
See the list of time zones on Wikipedia. Sort by offset column. Notice how around three dozen time zones may today be sharing the offset of -03:00 such as America/Montevideo, Atlantic/Stanley, and Antarctica/Palmer.
Always prefer a time zone to a mere offset. When doing date-time math and adding/subracting spans of time, the results may vary by time zone. Time zones may be using different offsets other than -03:00 on other dates in the past and in the future.
You need to convert it first to ZonedDateTime, change the timezone, and then extract LocalDateTime from that:
ZoneId from = ...;
ZoneId to = ...;
LocalDateTime input = ...;
LocalDateTime output = input.atZone(from).withZoneSameInstant(to).toLocalDateTime();
Try this solution:
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
ZonedDateTime ldtZoned = ldt.atZone(ZoneId.systemDefault());
ZonedDateTime utcZoned = ldtZoned.withZoneSameInstant(ZoneId.of("UTC-3"));
System.out.println(utcZoned.toLocalDateTime());
It gives the output:
2020-02-03T20:55:33.313882
2020-02-03T17:55:33.313882
Related
Good day, it's not some errors. But can someone explain to me what happened here?
I'am using free sql database with Spring framework so basically my sql database was on the cloud. Then I'm inserted date time value to my database using my local time zone (Indonesia (GMT+8)). But the time zone is not correct with my time zone even I'm already used localdatetime.now()
This was the case :
Set up my localdatetime zone
LocalDateTime ldt = LocalDateTime.now();
Using my system default time zone
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
This is the output (My time zone showing at 22:47)
'2022-10-26 16:05:52'
Using (GMT+8)
ZonedDateTime gmt = zdt.withZoneSameInstant(ZoneId.of("GMT+8"));
This is the output (My time zone showing at 23:10)
''2022-10-26 17:10:30''
Using (GMT+12)
This is the output (My time zone showing at 23:15)
''2022-10-26 21:15:47''
Using (GMT+14) I'm even dont know anymore are this time zone literally correct
This is the output (My time zone showing at 23:20)
''2022-10-26 23:20:47'' This was my time zone (basically, this is the right one)
Using GMT+14 was right according to my own clock, but my time zone (Indonesia, GMT+8). Then I'm checked to my server where my database are located at the cloud, then I found it at Asia Pacific.
This is my lines of code :
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
ZonedDateTime gmt = zdt.withZoneSameInstant(ZoneId.of("GMT+14"));
Timestamp timestamp = Timestamp.valueOf(gmt.toLocalDateTime());
transaction.setDate(timestamp);
transactionServices.saveTransaction(transaction);
So are this happened because where my database are located or because something else? Can someone explain so I can improve my code.
I'am expecting using GMT+8 not GMT+14, I'm affraid this can be a problem when this application is produced.
LocalDateTime.now()
I cannot imagine a scenario where calling LocalDateTime.now is the right thing to do.
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
Skip the LocalDateTime variable ldt. Just ask ZonedDateTime to capture the current moment as seen in your desired time zone.
ZoneId z = ZonedId.systemDefault() ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
ZonedDateTime gmt = zdt.withZoneSameInstant(ZoneId.of("GMT+8"));
For an offset, use the subclass ZoneOffset rather than ZoneID.
ZoneOffset offset = ZoneOffset.of( 8 ) ;
And, this code does not make sense in couple ways. Firstly, if you want to represent a moment as seen through an offset, use OffsetDateTime.
OffsetDateTime odt = OffsetDateTime.now( offset ) ;
Secondly, you should generally 👉 prefer a time zone to a mere offset. When adding or subtracting to move through time, using a mere offset means you will fail to account for changes to the offset used by the people in a particular time zone. For example, you will fail to account for Daylight Saving Time (DST) cut-overs. DST is only one example; politicians frequently change the offset of the time zones under their jurisdiction for various reasons including diplomatic, martial, practical, and fashionable.
A reminder of definitions:
An offset is merely a number of hours, minutes, and seconds ahead of, or behind, UTC.
A time zone is much more. A time zone is a named history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians.
For example, the time zone Australia/Perth currently uses an offset of +08:00.
ZoneId z = ZoneId.of( "Australia/Perth" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
By the way, stick with standard ISO 8601 formats for date-time values. So use +08:00 rather than "GMT+8". And I recommend always (a) including both hours and minutes, and (b) using padding zero for single-digit numbers. I have seen more than one library that expects only such values.
Tripping through time zones
You say your own time zone is in Indonesia. I will presume you mean Asia/Jakarta.
Capture the current moment as seen there.
ZoneId zJakarta = ZoneId.of( "Asia/Jakarta" ) ;
ZonedDateTime zdtJakarta = ZonedDateTime.now( zJakarta ) ;
Adjust to UTC, meaning an offset from UTC of zero hours-minutes-seconds. Simply extract a Instant. An Instant is always in UTC, by definition.
Instant instant = zdt.toInstant() ;
Adjust from UTC to another time zone.
ZoneId zEdmonton = ZoneId.of( "America/Edmonton" ) ;
ZonedDateTime zdtEdmonton = instant.atZone( zEdmonton ) ;
Or skip the Instant class. Move from Indonesia time to Canada time.
ZonedDateTime zdtEdmonton = zdtJakarta.withZoneSameInstant( zEdmonton ) ;
👉 Note that all of these moment objects (zdtJakarta, instant, zdtEdmonton) refer to the very same simultaneous moment. All three represent the same point on the time line, just different wall-clock/wall-calendar time.
Avoid legacy classes
Your code:
Timestamp timestamp = Timestamp.valueOf(gmt.toLocalDateTime());
transaction.setDate(timestamp);
👉 Never use the terribly flawed java.sql.Timestamp. This is one of the bloody awful date-time classes that are now legacy, years ago supplanted by the modern java.time classes.
Do not bother trying to study the behavior of these classes. Unless you want a masterclass in how to not design an object-oriented time-tracking framework.
Sun, Oracle, and the JCP community all gave up on the legacy classes with the adoption of JSR 310. I suggest you do the same.
Database
To write a moment to a database, 👉 use OffsetDateTime. Standard SQL lacks the concept of a ZonedDateTime.
To store a moment, a point on the time line, be sure your database table column is of a type akin to the SQL standard type TIMESTAMP WITH TIME ZONE rather than WITHOUT.
ZonedDateTime zdt = … ;
OffsetDateTime odt = zdt.toOffsetDateTime() ; // Discard time zone, keeping only the offset.
myPreparedStatement.setObject( … , odt ) ;
Retrieve.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZonedDateTime zdt = odt.withOffsetSameInstant( myZoneId ) ;
You said:
So are this happened because where my database are located
Do not write code that depends on the current default time zone of your database session, the server OS, or your JVM. If you write database code as I showed here, you are in control of the time zone adjustments.
Not a moment
Notice that nowhere did I use the LocalDateTime class. That is because your Question is asking about moments, specific points on the time line.
A LocalDateTime contains only a date and a time-of-day. The class purposely lacks the concept of a time zone or offset. Therefore, the values in LocalDateTime objects are inherently ambiguous. If you say "noon on the 23rd of January 2023", I have no idea if you mean noon in Tokyo, noon in Toulouse, or noon in Toledo — three different moments several hours apart.
👉 LocalDateTime cannot represent a moment.
The equivalent type in standard SQL is TIMESTAMP WITHOUT TIME ZONE.
All this and more has been covered many many times already on Stack Overflow. Search to learn more.
got a little problem in Java: I've got two strings, representing a date (for example "2019-11-10") and a time (for example "01:23:45.123"). Converting those into a UTC timestamp is easy enough, but there is one problem:
The date is given in a local timezone, for example "America/New_York", while the time is given in UTC, so the following information...
date = "2019-11-10", time="01:23:45.123" (assuming a local timezone of "America/New_York" for the date part)
...would actually be the UTC time "2019-11-11 01:23:45.123" (since only this would be a New York date of "2019-11-10").
Does the Java Time API or joda time offer any convenient method to do this conversion while keeping also details like DST, etc. in mind? Is there a (relatively) simple way of doing this at all?
Edit:
Perhaps this was a bit unclear. Let me try to explain it from the other side:
Assuming I have a DateTime x (in UTC) of "2019-11-11 01:23:45.123".
Then I can get the date part y (as seen in "America/New_York") by simply converting x into the appropriate timezone and formatting is accordingly -> "2019-11-10".
I can also get the time part z (as seen in UTC) by simply formatting is accordingly - "01:23:45.123".
Now, assuming I've got y and z - How do I get x?
Edit 2:
I just realized, this will never work perfectly. Reason:
UTC "2019-11-04 04:01:00.000" -> US/NY : "2019-11-03 23:01"
UTC "2019-11-03 04:01:00.000" -> US/NY : "2019-11-03 00:01"
So, if I only got the information "date in US/NY" is "2019-11-03" plus "time in UTC" is "04:01:00.000" there are actually two possible solutions and not only one.
You have to adjust the date to be in the New York time zone which can be done by choosing an arbitrary time. Then convert the time to New York by choosing an arbitrary date. The two can then be merged as they have the same zone. And convert back to UTC
LocalDate date = LocalDate.parse("2019-11-10");
LocalTime time = LocalTime.parse("01:23:45.123");
ZoneId zone = ZoneId.of("America/New_York");
ZonedDateTime dateInZone = date.atStartOfDay(zone);
ZonedDateTime timeInZone = time.atOffset(ZoneOffset.UTC).atDate(date).atZoneSameInstant(zone);
ZonedDateTime resultNY = dateInZone.with(timeInZone.toLocalTime());
ZonedDateTime resultUTC = resultNY.withZoneSameInstant(ZoneOffset.UTC)
System.out.println(resultUTC);
// 2019-11-11T01:23:45.123Z
A date cannot have a time zone. (Think about it.)
Perhaps what you mean is the first moment of the day for that date as seen in UTC.
LocalDate ld = LocalDate.parse( "2019-11-10" ) ;
ZonedDateTime zdt = ld.atStartOfDay( ZoneOffset.UTC ) ;
Adjust that moment to be seen in a time zone.
ZoneId z = ZoneId.of( "America/New_York" ) ;
LocalTime lt = LocalTime.parse( "01:23:45.123" ) ;
ZonedDateTime zdt2 = zdt.with( lt ) ;
This is not clear to me. For some reason when I am trying to format LocalDateTime instance using DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withLocale(...), I am getting an exception:
java.time.DateTimeException: Unable to extract value: class
java.time.LocalDateTime
It happens only if I am using FormatStyle.LONG, works fine for FormatStyle.MEDIUM, for example.
Here is my test:
#Test
public void dateTest() {
LocalDateTime now = LocalDateTime.now();
// this is ok. prints a value
System.out.println("LocalDateTime now (formatted with locale): "
+ now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
.withLocale(new Locale("it"))));
// this fails with java.time.DateTimeException: Unable to extract value: class java.time.LocalDateTime
// only if FormatStyle.LONG (as it is now)
System.out.println("LocalDateTime now (formatted with locale): "
+ now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
.withLocale(new Locale("it"))));
}
Is there any good explanation for that?
With FormatStyle.LONG You have to use :
ZonedDateTime.now()
Instead of :
LocalDateTime.now()
Because ZonedDateTime gives you lots of detail, not like LocalDateTime.
When you use FormatStyle.LONG, the formater search for other information like ZoneId which is not found in LocalDateTime, so you get exceptions
tl;dr
Is there any good explanation for that?
Yes.
The LONG and FULL formats requires a time zone or offset-from-UTC. Your LocalDateTime lacks any zone or offset.
Your use of LocalDateTime.now is incorrect. You should only capture the current moment with Instant (or OffsetDateTime/ZonedDateTime).
Instant.now() // Capture the current moment as seen in UTC.
For more flexibility in generating strings, use OffsetDateTime or ZonedDateTime.
ZonedDateTime.now(
ZoneId.of( "Pacific/Auckland" )
)
.format(
DateTimeFormatter.ofLocalizedDateTime(
FormatStyle.LONG // Or `FULL`.
)
.withLocale( Locale.ITALY )
)
6 marzo 2019 10:22:23 NZDT
And, with FormatStyle.FULL:
mercoledì 6 marzo 2019 10:23:25 Ora legale della Nuova Zelanda
LocalDateTime is not a moment
The LocalDateTime class is simply a date and a time-of-day. It purposely lacks any concept of time zone or offset-from-UTC. So, by definition, it cannot represent a moment.
Never call LocalDateTime.now()
LocalDateTime.now();
Never do this, never call now on LocalDateTime. I cannot think of any practical situation would ever call for that.
Never use LocalDateTime when tracking moments. A LocalDateTime is merely a date and a time-of-day, and nothing more. Without the context of a time zone or offset-from-UTC, a LocalDateTime cannot represent a moment. It represents potential moments along a range of about 26-27 hours, the current range of time zones around the globe.
A LocalDateTime is like saying “noon on the 23rd of January this year”. Do you mean noon in Tokyo Japan or Kolkata India? Or maybe Paris France? Montréal Québec? Noon in these various places happen at different moments, with hours elapsed between each.
The “Local” in LocalDateTime means any locality, or every locality, but does not mean any particular locality.
Capturing the current moment
To track a moment, use one of these classes:
InstantA moment in UTC, always in UTC
OffsetDateTimeA moment with an offset-from-UTC, that is, a number of hours-minutes-seconds ahead of or behind the baseline of UTC (the meridian at Royal Observatory in Greenwich).
ZonedDateTimeA moment as seen through the wall-clock time used by the people of a particular region (a time zone).
Generally, best practice is to work in UTC and forget about your own parochial time zone.
Instant instant = Instant.now() ;
If you want to use the wall-clock time of some region:
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( instant ) ;
Both the instant and the zdt represent the very same simultaneous moment, the same single point on the timeline. Only the wall-clock time is different.
Or you can skip the Instant.
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
Formats LONG & FULL require a time zone
These two format styles:
FormatStyle.LONG
FormatStyle.FULL
…both require a time zone as part of their display.
As discussed above, a LocalDateTime object has no zone or offset. So it makes no sense to use the LONG or FUL formats with such an object.
Tip: LocalDateTime is not often the class you want in most common business-oriented apps. Only use that class when you have a specific issue clearly in mind, such as booking appointments far enough out in the future that you run the risk of politicians redefining the offset of your time zone (which they often do, in most any polity). When tracking a specific moment, think first of using Instant.
below is the code I have to print out the current EST date time, but it prints out time in my Time zone which is Arizona Time. What am I missing in this code. Thankyou!
public static void main(String args[]) {
LocalDateTime datetime = LocalDateTime .now();
ZonedDateTime zdtNewYork = ZonedDateTime.of ( datetime , ZoneId.of ( "America/New_York" ) );
System.out.println(zdtNewYork.format(DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss.SSS")));
}
tl;dr
You captured Arizona date and time-of-day, then slapped on a time zone to claim (incorrectly) that New York has the same time-of-day at that moment.
So of course when you generated text to display these values, you saw the time-of-day first captured in Arizona. At no point did you adjust from Arizona to New York.
LocalDateTime is the wrong class
Never use LocalDateTime for tracking moments. By definition, that class cannot represent a specific moment in time, a point on the timeline. It holds a date and time-of-day but lacks the context of a time zone or offset-from-UTC. Telling us "Noon on the 23rd of January this year" is meaningless if we do not know whether you meant noon in Tokyo Japan, Kolkata India, Paris France, or Montréal Québec — all very different moments, hours apart.
Always specify time zone
To compound on using the wrong class, you called LocalDateTime.now without specifying the time zone. So your JVM’s current default time zone was implicitly applied. You claim that default is some time zone in Arizona. So that would be zone applied.
So, you captured the date & time-of-day as seen in Arizona. But then you discarded the fact that the value was in Arizona time zone, because of your use of LocalDateTime. Discarding the time zone is the entire point of the LocalDateTime class. There are cases where that is useful, but certainly not in your situation.
You then took that Arizona date & time-of-day, and claimed that was the date and time in New York. The actual time-of-day in New York was hours ahead of that, so you told a fib. Lastly you generated text showing that fib.
In other words, apparently you thought this line:
ZonedDateTime.of ( datetime , ZoneId.of ( "America/New_York" ) )
…adjusted from Arizona to New York. But that datetime argument no longer knows it came from Arizona, because LocalDateTime has no concept of zone/offset. No adjustment was made.
You can think of it this way:
LocalDateTime = date + time-of-day
OffsetDateTime = date + time-of-day + offset
ZonedDateTime = date + time-of-day + zone
Instant = date + time-of-day + UTC
Instead, I recommend always specifying explicitly your desired/expected time zone. Even if you want the current default time zone, say so explicitly by calling ZoneId.systemDefault so any programmer reading your code knows your intention clearly. Letting the time zone or offset-from-UTC be optional is one of the few things I would change in the otherwise amazing class design found in java.time. Making the zone/offset arguments required would help to educate more programmers about date-time handling.
ZonedDateTime is the right class
To represent a moment as seen through the wall-clock time used by the people of a particular region (a time zone), use ZonedDateTime.
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
See this code run live at IdeOne.com.
zdt.toString(): 2019-03-04T18:17:08.014-05:00[America/New_York]
Generate text
We can generate the text you want easily.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu HH:mm:ss.SSS" ) ;
String output = zdt.format( f ) ;
See this code run live at IdeOne.com.
03/04/2019 18:17:08.014
Adjusting zones
If you do want to adjust between zones, call the ZonedDateTime::withZoneSameInstant method.
ZonedDateTime zdtPhoenix = ZoneDateTime.now( ZoneId.of( "America/Phoenix" ) ) ;
ZonedDateTime zdtNewYork = zdtPhoenix.withZoneSameInstant( ZoneId.of( "America/New_York" ) ) ; // Same moment, same point on the timeline, different wall-clock time.
Notice the phrase SameInstant that means you want the same moment, the same simultaneous point on the timeline, but you want to see it through the wall-clock time used by the people of the New York region.
Time zones
print out the current EST date time
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use or refer to the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
Try something like:
LocalDateTime datetime = LocalDateTime .now(ZoneId.of ( "America/New_York" ));
System.out.println(datetime.format(DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss.SSS")));
I'm getting start date as "2016-06-01" and end date as "2016-07-01" (in string format) for searching records in MongoDB. Need pointer/guidance to append start time (00:00:00.000) to start date and maximum time(23.59.59.999) to end date as below in Java using java.util.Date or any others which supported by MongoDB.
Example :
Start Date+with time : 2016-06-01T00:00:00.000
End Date+with time : 2016-07-01T23:59:59.999
You could use the DateTimeFormatter.ISO_LOCAL_DATE_TIME for this. Here is an example that might shed some light on what you are trying to do:
DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
String startTime = "T00:00:00.000";
String endTime = "T23:59:59.999";
//here I used the LocalDateTime parser to parse the data+startTime/endTime
LocalDateTime startLocalDateTime = LocalDateTime.parse("2016-07-01"+startTime);
LocalDateTime endLocalDateTime = LocalDateTime.parse("2016-07-01"+endTime );
//with the LocalDateTime, you can then to whatever you want
//as an example, I am parsing it using ISO_LOCAL_DATE_TIME :
String strinStartTime= dtf.format(LocalDateTime.parse("2016-07-22"+startTime));
I hope this helps;
tl;dr
ZoneId zoneId = ZoneId.of( "Europe/Paris" ) ;
LocalDate startDate = LocalDate.of( "2016-06-01" ) ;
ZonedDateTime zdt start = startDate.atStartOfDay( zoneId ) ;
ZonedDateTime zdt stop = startDate.plusMonths(1).atStartOfDay( zoneId ) ;
// Perform database search where ( ( x >= start ) AND ( x < stop ) ) . Notice '>=' versus '<' with no 'equals' on the latter.
If you need strings…
String outputStart = start.toInstant().toString() ; // 2016-05-31T22:00:00Z Paris in the summer is two hours ahead of UTC.
String outputStop = stop.toInstant().toString() ; // 2016-06-30T22:00:00Z
Details
The Answer by ishmaelMakitla is good in that it points to using the java.time classes built into Java 8 and later. But it focuses on strings rather than objects. Also it does not discuss the crucial issue of time zone.
The java.time classes include:
LocalDate for a date-only value with no time-of-day and no time zone.
LocalTime for a time-of-day value without a date and without a time zone.
LocalDate startDate = LocalDate.parse( "2016-06-01" ); // Parsing ISO 8601 standard date format.
LocalTime startTime = LocalTime.MIN; // '00:00'.
Both of those classes can be used in factory methods to instantiate LocalDateTime and other classes.
LocalDateTime ldt = LocalDateTime.of( startDate , startTime );
In code above we used LocalTime.MIN to get 00:00. To directly answer your Question, you can also use LocalTime.MAX in the same way to get 23:59:59.999999999. But I do not recommend doing so. Read below about "Half-Open".
Time zone
Time zone is crucial in determining a date and a time. For any given moment the date and the hour-of-day both vary by time zone. A few minutes after midnight in Paris is a new day while still “yesterday” in Montréal.
The Local… types are not actual moments on the timeline. They represent a vague idea about possible moments. As noted above, the first moment of June 1st in Paris is simultaneously May 31st at 6 PM in Montréal. So before performing your database search you need to assign a time zone to your LocalDateTime. Applying a ZoneId produces a ZonedDateTime object.
Perhaps your date-time was intended to be Paris.
ZoneId zoneId = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdt = ldt.atZone( zoneId );
Or perhaps you intended UTC. This all depends on your business rules, the context in which your app operates. For UTC, we use OffsetDateTime as UTC is not a full time zone but rather a mere offset-from-UTC. A time zone is an offset plus a set of rules for handling anomalies such as Daylight Saving Time (DST).
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
To get a string as asked for in the Question, extract LocalDate and call toString(). But I do not recommend this as it ignores time zone (read on down below).
String output = odt.toLocalDateTime.toString(); // Not likely to be what you really need.
Best practice in databases is to store the date-time in UTC. I don't know about MongoDB. Be sure to read the doc on how your database driver in Java may be affecting/translating the values you specify.
Start of Day
Be aware that a day does not always start at 00:00:00. In some time zones DST or other anomalies means the day may start at some other time such as 01:00.
The java.time classes will make adjustments as needed in some situations. Be sure to read the class doc so you see if the behavior matches your expectations & needs.
You can ask java.time to find the starting time.
ZonedDateTime zdt = LocalDate.of( "2016-06-01" ).atStartOfDay( zoneId );
Half-Open
Your attempt to determine the end of the day is a problem. That last second is infinitely divisible. Traditional Unix-oriented libraries resolve to whole seconds, the old date-time classes in Java resolve to milliseconds, some databases like Postgres may resolve to microseconds, and java.time and other databases such as H2 resolve to nanoseconds. Do not get in the middle of that.
Generally in date-time programming of a span of time, the best practice is "Half-Open". The beginning of the span is inclusive while the ending is exclusive.
So searching for a month of data in Paris zone means searching for records where the date-time is equal to or later than the start and less than (but not including) the stop.
ZoneId zoneId = ZoneId.of( "Europe/Paris" );
LocalDate startDate = LocalDate.of( "2016-06-01" );
ZonedDateTime zdt start = startDate.atStartOfDay( zoneId );
ZonedDateTime zdt stop = startDate.plusMonths(1).atStartOfDay( zoneId );
// Perform database search where ( ( x >= start ) AND ( x < stop ) ) . Notice '>=' versus '<' with no 'equals' on the latter.
Similarly, the month of records for UTC rather than Paris.
ZoneOffset zoneOffset = ZoneOffset.UTC;
LocalDate startDate = LocalDate.of( "2016-06-01" );
OffsetDateTime start = OffsetDateTime.of( startDate , zoneOffset );
OffsetDateTime stop = OffsetDateTime.plusMonths(1).of( startDate , zoneOffset );
// Perform database search where ( ( x >= start ) AND ( x < stop ) ) . Notice '>=' versus '<' with no 'equals' on the latter.
Using the Half-Open approach consistently throughout your app where handling spans of time will make your code more sensible and easier to understand. You can also train your users to think this way. We all use Half-Open intuitively in situations situations like "Lunch break is from 12:00 to 13:00". We all know this means be back from lunch before the clock strikes 13:00:00.0.
public class DateSample {
public static void main(String[] args) throws ParseException {
String startDate = "2016-06-01";
String endDate = "2016-07-01";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date strDate = formatter.parse(startDate+" 00:00:00.000");
Date enDate = formatter.parse(endDate+" 23:59:59.999");
System.out.println(formatter.format(strDate));
System.out.println(formatter.format(enDate));
}
}
You will get
2016-06-01 00:00:00
2016-07-01 23:59:59
If you are running under jdk 1.8, use LocalDateTime
LocalDateTime is an embedded api of jdk 1.8. You can found explaination here docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html. You can use minus* or plus*, and parse methods