I have a SQL Timestamp String, e. g.
String timestamp = 2016-12-11 14:26:35
I want to get the difference to the day today, and the String in the form
11.12.206 14:26:35
I think to do this, I have to get the milliseconds from the object and parse them to a date / calendar object?
How to do this or is there an easier way?
These issues have been discussed many times already on Stack Overflow. Yours is a duplicate of many other Questions. So search for details. Search for the class names seen below and for words such as elapsed.
Here is a brief nutshell answer.
ISO 8601
Convert your input string from SQL format to standard ISO 8601 format by replacing the SPACE in the middle with a T.
String input = "2016-12-11 14:26:35".replace( " " , "T" );
LocalDateTime
Parse as a LocalDateTime as this string lacks any indication of time zone or offset-from-UTC.
LocalDateTime ldt = LocalDateTime.parse( input );
ZonedDateTime
Apply the time zone intended as the meaning behind this string. Did you mean two in the afternoon of Auckland, Paris, or Montréal?
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtThen = ldt.atZone( z );
Get the current moment. Again, the time zone is crucial. Cannot be ignored or wished away.
ZonedDateTime zdtNow = ZonedDateTime.now( z );
Difference?
As for "get the difference", you do not explain what that means.
If you want to represent a span of time in between as whole days, use Period.
Period p = Period.between( zdtThen.toLocalDate() , zdtNow.toLocalDate() );
If you want hour-minutes-seconds elapsed, use Duration.
Duration d = Duration.between( zdtThen , zdtNow );
To track as a pair of points in time, obtain the ThreeTen-Extra library, and use Interval class.
Interval interval = Interval.of( zdtThen.toInstant() , zdtNow.toInstant() );
If I understand your question, you just have to convert your SQL timestamp to an Object Data. It's can be done with SimpleDateFormat.
See here https://www.mkyong.com/java/how-to-convert-string-to-date-java/
After that, you can make the difference between two date easilly with joda-time.
Cheers
Related
In our database, we have few long values like below
modified=1636334664000
created=1636334664000
if i use below code to convert, it doesnt show the format in millisec in it, it shows only up to seconds.
i have used below code
long modified = 1636334664000l;
LocalDateTime ldt = LocalDateTime.ofInstant(
Instant.ofEpochMilli(modified), ZoneId.systemDefault());
LocalDateTime dateTime = LocalDateTime.parse(ldt.toString());
dateTime = dateTime.atZone(ZoneId.systemDefault())
.withZoneSameInstant(ZoneOffset.UTC)
.toLocalDateTime();
Instant insStr = dateTime.toInstant(ZoneOffset.UTC);
this gives me output as "2021-11-08T01:24:24Z" but i was expecting as "2021-11-08T01:24:24.000Z".
used Java 8 date conversion as above.
tl;dr
After 👉🏽 correcting multiple typos in the example data of your Question, we find no errors, no surprises, when running the code. Your millisecond appears as expected.
Instant.ofEpochMilli( 1_636_334_664_001L ).toString()
2021-11-08T01:24:24.001Z
LocalDateTime not helpful in your case
LocalDateTime is the wrong class to use here. That class represents a date with time-of-day but lacks the context of a time zone or offset-from-UTC. So that class cannot represent a moment, a specific point on the timeline.
To track moments use:
Instant
OffsetDateTime
ZonedDateTime
Use Instant
Assuming your long values represent a count of milliseconds since the epoch reference of first moment of 1970 in UTC, 1970-01-01T00:00Z, use Instant.ofEpochMilli.
Your 1636334664000l example presumably has a typo, one too many zero digits. I will go with 163633466400l.
When hard-coding such long values, use the optional underscore (_) digit grouping feature in Java. And 👉🏽 append an L to ensure parsing as a long primitive.
Instant created = Instant.ofEpochMilli( 1_636_334_664_000L ) ;
Instant modified = Instant.ofEpochMilli( 1_636_334_664_001L ) ;
Calculate elapsed time.
Duration duration = Duration.between( created , modified ) ;
We expect to see a single millisecond as our result. The result is presented in standard ISO 8601 format.
Dump to console.
System.out.println( created ) ;
System.out.println( modified ) ;
System.out.println( duration ) ;
Execute at Ideone.com. We see your expected fractional second, a millisecond.
2021-11-08T01:24:24Z
2021-11-08T01:24:24.001Z
PT0.001S
ZonedDateTime
See that same moment through the wall-clock time of a particular time zone.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdtModifiedTokyo = instant.atZone( z ) ;
We continue to see your fractional second, a single millisecond.
zdtModifiedTokyo.toString(): 2021-11-08T10:24:24.001+09:00[Asia/Tokyo]
I am trying to get the start time (00:00:00) and the end time (23:59:59) of a day in the PST time zone. I have tried the following code, but for some reason, I am only getting the start and end times in UTC. I have tried changing the timezone to include "America/Los_angeles", but the output timestamp is always showing start and end times for GMT/UTC.
My code:
val time_zone = ZoneId.of("America/Los_Angeles")
val today_date = LocalDate.now(time_zone).plusDays(0)
val start_time = today_date + " " + "00:00:00"
val end_time = today_date + " " + "23:59:59"
val date_format = new SimpleDateFormat("yyyy-MM-dd");
val start_millis = date_format.parse(start_time).getTime();
val end_millis = date_format.parse(end_time).getTime();
start_millis
Output:
res375: Long = 1656460799000
In the epoch converter, 1656460799000 gives me this:
Anything I am missing here? Should I update any package, etc.?
java.time
The modern approach uses the java.time classes only.
No need to ever use SimpleDateFormat, Date, Calendar, and the other terrible legacy date-time classes. If need be, you can convert to and fro via new conversion methods added to the old classes.
Start of day
I am trying to get the start time (00:00:00)
Do not assume the day starts at 00:00. Some dates in some zones start at another time such as 01:00. Let java.time determine the first moment of the day using LocalDate#atStartOfDay.
End of day
the end time (23:59:59) of a day
You would be missing an entire last second of the day with that approach.
Date-time work is commonly done with the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. So a day starts with the first moment of the day, and runs up to, but does not include, the first moment of the following day. Half-Open approach neatly contains that full last second of the day.
Time zones
PST time zone.
There is no such thing as a time zone named PST. Such 2-4 letter pseudo-zones are used by the popular media to indicate a hint about the time zone. But these pseudo-zones are not standardized, and are not even unique! Use only for localized presentation to humans, never for data storage or data exchange.
Real time zones are named with Continent/Region.
Perhaps by “PST” you meant “Pacific Standard Time”, which often indicates America/Tijuana, or America/Los_Angeles or America/Vancouver or others.
Or perhaps by “PST” you meant “Philippines Standard Time” covering the Asia/Manila time zone.
Example code
Capture the current moment as seen in a time zone.
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
Extract the date.
LocalDate today = zdt.toLocalDate() ;
Determine the first moment of the day.
ZonedDateTime zdtStartOfDay = today.atStartOfDay( z ) ;
And determine the first moment of the following day.
ZonedDateTime zdtStartOfFollowingDay = today.plusDays( 1 ).atStartOfDay( z ) ;
You may want to see the length of time. Not all days are 24 hours.
Duration d = Duration.between( zdtStartOfDay , zdtStartOfFollowingDay ) ;
Adjust both moments to UTC by extracting an Instant object. That class represents a moment as seen in UTC.
Instant start = zdtStartOfDay.toInstant() ;
Instant end = zdtStartOfFollowingDay.toInstant() ;
For each, get the count of milliseconds since the epoch reference of first moment of 1970 as seen in UTC, 1970-01-01T00:00Z.
long startMilli = start.toEpochMilli() ;
long endMilli = end.toEpochMilli() ;
However, I strongly recommend against tracking time as a count of milliseconds. This approach is confusing, as at least a couple dozen epoch reference points are commonly used. And a long cannot be interpreted by a human reader, so mistakes may go unnoticed.
Instead, data storage and data exchange should generally be done as text using the standard ISO 8601 formats. The java.time classes use these standard formats by default when parsing/generating text.
String startText = start.toString() ;
String endText = end.toString() ;
ThreeTen-Extra
You may want to add the ThreeTen-Extra library to your project. This gives you access to the Interval class, to represent a span of time as a pair of Instant objects.
Interval allDayLongToday = org.threeten.extra.Interval.of( start , end ) ;
This class provides several helpful methods. These include contains, encloses, abuts, union, intersection, and more.
Instant invoiceRecorded = … some `Instant` ;
boolean invoiceRecordedToday = allDayLongToday.contains( invoiceRecorded ) ;
Just add this section to your code:
date_format.setTimeZone(TimeZone.getTimeZone("PST"));
Then it will work as you want :)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have a string date. Eg: "2020-02-21 16:36:30.072" and I want to convert it to Date "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'". (i.e. 2020-02-21T16:36:30.072+05:30)
How? Could you please help me?
You need to start by converting the String into a more "malleable" format - something which can represent the date/time in a way through which you can generate different formats based on your need
Since it's 2020, you should start with the java.time.* API.
String input = "2020-02-21 16:36:30.072";
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
LocalDateTime ldt = LocalDateTime.parse(input, inputFormatter);
Ok, now, part of your requirement is to have the time zone, so you'll need to convert the LocalDateTime to a ZonedDateTime, you could, technically, do this in a single step, but it's a good demonstration
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
DateTimeFormatter outputFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
String output = outputFormatter.format(zdt);
System.out.println(input);
System.out.println(output);
This will output
2020-02-21 16:36:30.072
2020-02-21T16:36:30.072+11:00
I live in Australia, so my time zone is +10 (and +1 for daylight savings). You can specify a specific time zone if you wish, this is just for demonstration (and I couldn't be bothered trying to figure out 530+ time zone ;))
tl;dr
Here is a one-liner.
LocalDateTime
.parse(
"2020-02-21 16:36:30.072".replace( " " , "T" )
) // Returns a `LocalDateTime` object. *Not* a moment, *not* a point on the timeline. Just a date and a time-of-day, nothing more. Lacks context of a time zone or offset-from-UTC.
.atZone( // Lending context to our `LocalDateTime` object to determine a moment by assigning a time zone.
ZoneId.of( "Asia/Kolkata" ) // Currently using an offset of five and a half hours ahead of UTC.
) // Returns a `ZonedDateTime` object.
.format( // Generates text representing the value of the `ZonedDateTime` object.
DateTimeFormatter.ISO_OFFSET_DATE_TIME // Pre-defined formatter. No need to specify your own formatting pattern. Your desired format complies with the ISO 8601 standard.
) // Returns a `String`.
See this code run live at IdeOne.com.
2020-02-21T16:36:30.072+05:30
Details
The Answer by MadProgrammer is correct and nicely detailed. I will take some shortcuts, and address specifically your desired offset of +05:30.
We can parse your input as a LocalDateTime by merely replacing the SPACE character in the middle with an uppercase T.
String input = "2020-02-21 16:36:30.072".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
A LocalDateTime does not represent a moment, is not a point on the timeline. It lacks the context of a time zone or offset-from-UTC.
Your desired offset of +05:30 is currently used in only two time zones:
Asia/Colombo (Sri Lanka)
Asia/Kolkata (India)
Pick which one is yours.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
Apply to your LocalDateTime to determine a moment, resulting in a ZonedDateTime.
ZonedDateTime zdt = ldt.atZone( z ) ;
Generate a String in standard ISO 8601 format extended wisely to append the name of the zone in square brackets.
String output = zdt.toString() ;
If you really want the offset only without the time zone, keep in mind that readers of your data won't know for sure if you meant Sri Lanka time or India time. If you insist, use the predefined DateTimeFormatter object as shown in the other Answer.
import java.util.Date;
public class Test {
public static void main(String[] args) {
String s0="2020-02-21 16:36:30.072";
Date date=new Date();
String sd=s0.split(" ")[0];
date.setDate(Integer.parseInt(sd.split("-")[2]));
date.setMonth(Integer.parseInt(sd.split("-")[1])-1);
date.setYear(Integer.parseInt(sd.split("-")[0])-1900);
String st=s0.split(" ")[1];
date.setSeconds((int) Double.parseDouble(st.split(":")[2]));
date.setMinutes(Integer.parseInt(st.split(":")[1]));
date.setHours(Integer.parseInt(st.split(":")[0]));
System.out.print(date);
}
}
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 ) ;
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