millisec not showing in localdatetime from long value conversion - java

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]

Related

How to get number of days between two java.util.Date variables in scala?

I could not find any hand method on java.util.Date function in order to get number of days between 2 dates?
How should I get number of days?
First, convert your legacy java.util.Date objects to their modern replacements, java.time.Instant. Call new methods added to the old classes.
Instant start = myJavaUtilDate.toInstant() ;
If by “number of days” you mean “number of 24-hour chunks of time”, without regard for calendar, use Duration.
long days = Duration.between( start , end ).toDays() ;
If you meant calendar days, you need to specify the time zone by which you want to perceive dates.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
Apply that zone to Instant to produce a ZonedDateTime. Same moment, same point on the timeline, different wall-clock time and date.
ZonedDateTime startZdt = start.atZone( z ) ;
Calculate elapsed days using ChronoUnit enum DAYS.
long days = ChronoUnit.between( startZdt , endZdt ) ;

Calculate how often specific daytime is contained in time range

I have a time range starting with a start date and end date represented in milliseconds since 1970:
long start;
long end;
And I want to know if and how often a specific daytime is contained in this range. So let's say the daytime is 09.00 am DST - how often is it contained in the range.
Is there an easy and elegant way to calculate this in Java?
java.time
The modern approach uses the java.time classes.
Convert your count-from-epoch numbers. An Instant is a point on the timeline in UTC with a resolution of nanoseconds.
Instant startInstant = Instant.ofEpochMilli( startLong ) ;
Instant stopInstant = Instant.ofEpochMilli( stopLong ) ;
Adjust into your desired time zone.
Always use true time zone names structured as continent/region.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdtStart = instantStart.atZone( z ) ;
ZonedDateTime zdtStop = instantStop.atZone( z ) ;
Represent your target time-of-day.
LocalTime lt = LocalTime.of( 9 , 0 ) ;
Get a ZonedDateTime with your starting date and your target time.
ZonedDateTime zdtStartAtTargetTime = ZonedDateTime.of( zdtStart.toLocalDate() , lt , z ) ;
Compare that to your interval’s start to see if you should count this starting date.
Do the same process for the last day.
The count the days between the start of the second day and first moment of the last day.
long days = ChronoUnit.DAYS.between( start , stop ) ;
If they count, add your first day, and your last day.
Compare to the
If you're using Java 8, you could use java.time.OffsetDateTime, starting from your start point, adjusting the time based on toOffsetTime, then repeatedly using plusDays until you've exceeded your end time.
If not, then you can achieve something similar with Joda's DateTime class.
Don't try it without a library that handles calendars properly.

Convert LocalTime for given zone to unix epoch seconds without the date component in java

We received time as hour =11, minutes=29,seconds=54,milliseonds=999 along with timezone information.
How to convert this time to unix epoch milliseconds with no date part.
I have tried this code :
ZoneId zoneId = ZoneId.of("America/New_York");
LocalDate now = LocalDate.now(zoneId);
long epochMilli = ZonedDateTime.of(LocalDate.now(zoneId).atTime(11, 29, 20, 999 * 1000 * 1000), zoneId).toInstant().toEpochMilli();
long unixEpocSeconds = epochMilli % (24 * 60 * 60 * 1000); //86400000
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(zoneId));
calendar.setTimeInMillis(unixEpocSeconds);
System.out.println("( = " + (calendar.get(Calendar.HOUR)==11));
System.out.println("( = " + (calendar.get(Calendar.MINUTE)==29));
System.out.println("( = " + (calendar.get(Calendar.SECOND)==20));
System.out.println("( = " + (calendar.get(Calendar.MILLISECOND)==999));
How to get the unix epoch seconds without the date component i.e.how to get the milliseconds in UTC zone /rather than as give zoneid. Above code runs find if zoneId=UTC
tl;dr
Duration.ofHours( 11L )
.plusMinutes( 29L )
.plusSeconds( 54L )
.plusMillis( 999L )
.toMillis()
41394999
Span-of-time versus Time-of-day
Your Question is confused. A time-of-day without a date makes no sense in comparison to UTC. A count of milliseconds since the Unix epoch reference date of 1970-01-01T00:00:00Z is for tracking the date and the time-of-day.
I suspect you are actually dealing with a span of time, and mishandling that as a time-of-day. One is meant for the timeline, the other is not.
Duration
The java.time classes bundled with Java 8 and later include Duration for handling such spans of time unattached to the timeline.
These methods take long data type, hence the trailing L.
Duration d = Duration.ofHours( 11L ).plusMinutes( 29L ).plusSeconds( 54L ).plusMillis( 999L ) ;
Count of milliseconds
You asked for a count of milliseconds, so here you go. Beware of data loss, as a Duration carries a finer resolution of nanoseconds, so you would be lopping off any finer fraction of a second when converting to milliseconds.
long millis = d.toMillis() ; // Converts this duration to the total length in milliseconds.
41394999
But I suggest you not represent spans of time nor moments on the timeline using a count-of-milliseconds. Better to use objects or standardized text; read on.
ISO 8601
The ISO 8601 standard defines practical unambiguous formats for representing date-time values as text.
This includes representation of durations. The format is PnYnMnDTnHnMnS where the P marks the beginning while the T separates any years-months-days portion from any hours-minutes-seconds portion.
The java.time classes use the standard formats by default in their parse and toString methods.
String output = d.toString() ;
PT11H29M54.999S
See this code run live at IdeOne.com.
You can directly parse such strings in java.time.
Duration d = Duration.parse( "PT11H29M54.999S" ) ;
I suggest using this format whenever possible, certainly when exchanging data between systems.
While working inside Java, pass Duration objects around rather than mere text.
Timeline
You can perform date-time math with the Duration objects. For example, take the current moment in your particular time zone, and add the eleven and a half hours.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
ZonedDateTime later = now.plus( d ) ;
now.toString(): 2017-09-27T07:23:31.651+13:00[Pacific/Auckland]
later.toString(): 2017-09-27T18:53:26.650+13:00[Pacific/Auckland]
For UTC values, call toInstant. The Instant class represents a moment on the timeline in UTC with resolution of nanoseconds (finer than milliseconds).
Instant instant = later.toInstant() ;

Java: Datetime to Date object

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

Java - Adding/appending time start time(00:00:00.000) & end time (23.59.59.999) to date

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

Categories