This question already has answers here:
Java 8: Calculate difference between two ZonedDateTime
(3 answers)
Closed 5 years ago.
I have two Datetime strings:
val formatter = DateTimeFormatter.ofPattern("yyyy-MMM-dd-hh-mm-ss")
val startTime = formatter format ZonedDateTime.now(ZoneId.of("UTC"))
//...
val endTime = formatter format ZonedDateTime.now(ZoneId.of("UTC"))
How can I calculate the difference in seconds between endTime and startTime?
Use a java.time.temporal.ChronoUnit:
// difference in seconds
ChronoUnit.SECONDS.between(startTime, endTime)
But startTime and endTime must be ZonedDateTime objects, not Strings.
Just keep in mind that the result is floor-rounded - if the real difference is, let's say, 1999 milliseconds, the code above will return 1 (because 1999 milliseconds are not enough to make 2 seconds).
Another detail is that you can use ZoneOffset.UTC instead of ZoneId.of("UTC"), as the result is the same.
Actually, if you're working with UTC, why not use Instant.now() instead? The between method above works the same way with Instant's:
val start = Instant.now()
val end = Instant.now()
val diffInSecs = ChronoUnit.SECONDS.between(start, end)
Related
This question already has answers here:
Calculating the difference between two Java date instances
(45 answers)
Closed 2 years ago.
After searching for a while about this topic i found 3 methods of Calendar class isBefore(), isAfter() And isAfter() but this methods only returns true or false . So my question here is there a method or a way that allowed us to compare two dates and print how much they differ .
Example :
Calendar date1 = new GregorianCalendar(2020,12,01);
Calendar date1 = new GregorianCalendar(2020,12,20);
We should return 29 days .
If youre not forced to use the Calendar class for this, you can get a duration easily with the LocalDate and Duration classes.
LocalDateTime now = LocalDateTime.of(2020, 12, 01);
LocalDateTime future = LocalDateTime.of(2020, 12, 20);
Duration duration = Duration.between(now, future);
long days = duration.toDays();
NOTE: search Google before marking this question as duplicate. I did search and browse this question and all answers that I found were either for LocalDate, Joda or legacy Java Date.
It took me quite some time to investigate this so I've decided to share this as an answer.
I'd like a way to calculate the (approximate) number of months and days between two Java Instants (objects of java.time.Instant)?
First, what you are asking is not well-defined. For example between the instants 2020-03-01T06:00:00Z and 2020-03-31T05:00:00Z could be:
29 days 23 hours in Australia/Melbourne time zone;
30 days in Europe/Paris time zone;
1 month 1 day in America/Los_Angeles time zone.
Accurate result in a given time zone
ZoneId zone = ZoneId.of("America/Los_Angeles");
Instant start = Instant.parse("2020-03-01T06:00:00Z");
Instant end = Instant.parse("2020-03-31T05:00:00Z");
ZonedDateTime startZdt = start.atZone(zone);
LocalDate startDate = startZdt.toLocalDate();
ZonedDateTime endZdt = end.atZone(zone);
LocalDate endDate = endZdt.toLocalDate();
Period p = Period.between(startDate, endDate);
if (startZdt.plus(p).isAfter(endZdt)) {
// The time of day on the end date is earlier, so don’t count a full date
endDate = endDate.minusDays(1);
p = Period.between(startDate, endDate);
}
System.out.println(p);
Output:
P1M1D
Read as a period of 1 month 1 day.
Approximate result independent of time zone
Prefer to leave as much of the calculation to java.time as possible. This includes the estimate of the length of a month.
Duration diff = Duration.between(start, end);
Duration durationOfAMonth = ChronoUnit.MONTHS.getDuration();
long months = diff.dividedBy(durationOfAMonth);
diff = diff.minus(durationOfAMonth.multipliedBy(months));
long days = diff.toDays();
System.out.println("" + months + " months " + days + " days");
0 months 29 days
I've opted out to approximate solution (it assumes all months have 30.44 days). I've opted out to use something like this:
Duration duration = Duration.between(instant1, instant2).abs(); /* if want negative values remove .abs() */
long hours = duration.toHours();
double daysAndMonthsInDays = hours / 24.0;
int months = daysAndMonthsInDays / 30.44; //average number of days per month
int days = daysAndMonthsInDays - months * 30.44;
Please post another answer if there is a better solution using Duration class or something else. I've decided not to convert Instant to LocalDate and to perform the conversion on that level. That would not use an approximation of 30.44 days in a month, but rather the actual number.
This question already has answers here:
How to get milliseconds from LocalDateTime in Java 8
(14 answers)
Closed 3 years ago.
Executed piece of code :
String lapTime = "27:10.190";
int minutes = Integer.parseInt(lapTime.substring(0, lapTime.indexOf(":")));
int seconds = Integer.parseInt(lapTime.substring(lapTime.indexOf(":")+1, lapTime.indexOf(".")));
int milliseconds = Integer.parseInt(lapTime.substring(lapTime.indexOf(".")+1));
LocalTime localTime = LocalTime.of(0, minutes, seconds, milliseconds);
How to gain number of milliseconds of LocalTime localTime = LocalTime.of(0, minutes, seconds, milliseconds); ?
TL;DR Use Duration, not LocalTime. See end of answer.
Question code is incorrect
Be aware that the 4th argument to LocalTime.of() is nanosecond, not millisecond, which you'd see if you print localTime:
System.out.println(localTime); // prints: 00:27:10.000000190
So you need to change your code to:
LocalTime localTime = LocalTime.of(0, minutes, seconds, milliseconds * 1000000);
System.out.println(localTime); // prints: 00:27:10.190
Using LocalTime
If you wanted the milliseconds value back, call getLong(TemporalField field) with ChronoField.MILLI_OF_SECOND:
localTime.getLong(ChronoField.MILLI_OF_SECOND) // returns 190
To gain total number of milliseconds, i.e. not just the milliseconds value, use ChronoField.MILLI_OF_DAY as argument:
localTime.getLong(ChronoField.MILLI_OF_DAY) // returns 1630190
Using Duration
However, since the input is named lapTime, the LocalTime class is not the right tool for the job. E.g. your code will fail if minutes >= 60.
The right tool is the Duration class, e.g.
Duration duration = Duration.ofMinutes(minutes).plusSeconds(seconds).plusMillis(milliseconds);
Or:
Duration duration = Duration.ofSeconds(seconds, milliseconds * 1000000).plusMinutes(minutes);
You can then get the milliseconds directly by calling toMillis():
duration.toMillis(); // returns 1630190
That works even if the lap time exceeds one hour, e.g.
String lapTime = "127:10.190";
. . .
duration.toMillis(); // returns 7630190
In Java 9+, you can get the millisecond part back easily, by calling toMillisPart():
duration.toMillisPart(); // returns 190
To get the number of milliseconds within the second, you can do localTime.get(ChronoField.MILLI_OF_SECOND).
You can do localTime.toNanoOfDay() / 1000000 to get the number of milliseconds since the start of the day.
Since a LocalTime has no day or date associated with it, you can't directly get milliseconds-since-the-epoch.
You can attach a LocalDate to a LocalTime using LocalTime.atDate to get a LocalDateTime. Then you can call atZone, atOffset or toInstant to get an object that can return epochMillis.
This question already has an answer here:
Setting future date in Java 8
(1 answer)
Closed 4 years ago.
I have a solution for setting future/past date Java 8, but I would like to know if there is a cleaner way.
I have a method in which one of the argument is of type ZonedDateTime.
I am extracting the time, converting to milliseconds and subtracting that from present now.
void setFuturePastDate(ZonedDateTime dateTime) {
long diffInSeconds = ZonedDateTime.now().toEpochSecond()
- dateTime.toEpochSecond();
Duration durationInSeconds = Duration.ofSeconds(diffInSeconds);
Instant instantInSeconds = now.minusSeconds(durationInSeconds);
Clock clock = Clock.fixed(instantInSeconds, ZoneId.systemDefault());
System.out.println(ZonedDateTime.now(clock)); // - I have a past date
In Joda it was simple:
setCurrentMillisSystem(long)
and wherever we access new DateTime() it will give the date set.
Is there a cleaner way in Java 8 ?
void setFuturePastDate(ZonedDateTime dateTime) {
Clock clock = Clock.fixed(dateTime.toInstant(), ZoneId.systemDefault());
System.out.println(ZonedDateTime.now(clock)); // - I have a past date
}
This method prints the same ZonedDateTime as I passed in (provided it has the default zone).
If I understood you correctly, this is what you want:
void setFuturePastDate(LocalDateTime dateTime){
final LocalDateTime now = LocalDateTime.now();
final Duration duration = Duration.between(now, dateTime);
final LocalDateTime mirrored;
if(duration.isNegative()){
mirrored = now.minus(duration);
} else {
mirrored = now.plus(duration);
}
System.out.println(mirrored);
}
This mirrors the dateTime around the now(). E.g: 5 days in the past becomes 5 days in the future.
This question already has answers here:
Java: Converting an input of seconds into hours/minutes/seconds
(2 answers)
Closed 6 years ago.
How to convert from duration (in minutes) to hour and minutes?
For example: hour = 8 and minute = 25. Now person enter duration (in minutes) 60 for example. Now how to show time 9:25 because duration was 60 minutes?
You can use LocalTime provided in java.time.
LocalTime time = LocalTime.of(8, 25).plusMinutes(60);
System.out.println(time);
all date/time values in Java are internally in milliseconds. So multiply by the right factor to get milliseconds (60000 for minutes, 3600000 for hours). this can be added or subtracted from a date.
function addMinutes(startDate, minutes) {
var millis = startDate.getTime();
return new Date(millis + minutes*60000);
}
function addHours(startDate, hours) {
var millis = startDate.getTime();
return new Date(millis + hours*3600000);
}