I have this problem with calculating time difference in minutes.
Its working fine with exampples like calculating the difference between
2045 and 2300.
But when I want to calculate the difference between for example
2330 (today) and 0245 (tomorrow) I get a incorrect answer.
Code below:
// This example works
String dateStart = "2045";
String dateStop = "2300";
// This example doesnt work
//String dateStart = "2330";
//String dateStop = "0245";
// Custom date format
SimpleDateFormat format = new SimpleDateFormat("HHmm");
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
} catch (Exception e) {
e.printStackTrace();
}
long diff = d2.getTime() - d1.getTime();
long minutes = TimeUnit.MILLISECONDS.toMinutes(diff);
System.out.println("Time in minutes: " + minutes + " minutes.");
Thanks in advance
Consider using LocalDate, LocalDateTime, LocalTime ZonedDateTime classes from java.time.* package introduced in Java 8. They are very handy in use as they can address various corner cases (e.g. measuring minutes across different time zones, or during autumn and spring time change).
The thing to you need to know when you calculate time difference is that:
LocalTime contains time only
LocalDate contains date only (no time)
LocalDateTime contains both (date + time.)
ZonedDateTime contains date + time + timezone
This implies that difference between times will be different when you compare with:
LocalTime you can diff only time so 20:45 and 23:30 gives 2:45 of difference
LocalDate you cannot calculate any time diffs (contains no time)
LocalDateTime you can specify date and time, e.g.: 20:45 on 1Jan and 23:30 on 3Jan . Time difference will be 2:45 and 2 days of difference, or 50:45.
ZonedDateTime - same as LocalDateTime plus you takes into account DayLightSavings, so if the clock is changed overnight - it will get reflected.
Here is a snippet for a LocalDateTime:
LocalDateTime today2045 = LocalDateTime.of(
LocalDate.now(),
LocalTime.parse("20:45"));
LocalDateTime tomorrow0230 = LocalDateTime.of(
LocalDate.now().plusDays(1),
LocalTime.parse("02:30"));
System.out.println("Difference [minutes]: " +
Duration.between(today2045, tomorrow0230).toMinutes());
For ZonedDateTime taking into account spring/autumn clock changes:
ZonedDateTime today2045 = ZonedDateTime.of(
LocalDate.now(),
LocalTime.parse("20:45"),
ZoneId.systemDefault());
ZonedDateTime tomorrow0230 = ZonedDateTime.of(
LocalDate.now().plusDays(1),
LocalTime.parse("02:30"),
ZoneId.systemDefault());
System.out.println("Difference [minutes]: " +
Duration.between(today2045, tomorrow0230).toMinutes());
Some info on constructors can be found in Oracle's tutorial here.
This is not working because when you create a new date with just a time in it, it's assuming the day is "today".
What you could do is:
// This example works
String dateStart = "2045";
String dateStop = "2300";
// This example doesnt work
//String dateStart = "2330";
//String dateStop = "0245";
// Custom date format
SimpleDateFormat format = new SimpleDateFormat("HHmm");
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
} catch (Exception e) {
e.printStackTrace();
}
// MY ADDITION TO YOUR CODE STARTS HERE
if(d2.before(d1)){
Calendar c = Calendar.getInstance();
c.setTime(d2);
c.add(Calendar.DATE, 1);
d2 = c.getTime();
}
// ENDS HERE
long diff = d2.getTime() - d1.getTime();
long minutes = TimeUnit.MILLISECONDS.toMinutes(diff);
System.out.println("Time in minutes: " + minutes + " minutes.");
But you should consider using Java 8 new Date/Time features, or Joda Time.
You can add if statement to check if this is today, and if no you can add one day to this, since you are comparing time it wont be problem if you add full day
if(d2.before(d1)){
d2.setTime(d2.getTime()+86400000);
}
Try it out
This is a solved problem. If you look at the Joda Time library you'll find all the time and date manipulation functions you could possibly want:
In your case something along the lines of:
DateTime first = new DateTime(larger-time);
DateTime second = new DateTime(smaller-time);
DateTime difference = first.minusMillis(second.getMillis())
Joda will cope with all the odd edge conditions like rolling over between days/months/years, lengths of months, leap years, daylight savings, timezones...
Related
I am searching for a method to get the last third of two dates.
first example:
Date 1 = 22:00
Date 2 = 01:00 (next day)
calculateLastThird(); (output: 00:00)
second example:
Date 1 = 22:25
Date 2 = 01:45 (next day)
calculateLastThird(); (output: 00:38)
I already know how to get the midpoint between those two dates:
Date midpoint = new Date((date1.getTime() + date2.getTime()) / 2);
java.time
I recommend that you use java.time, the modern Java date and time API, for your date and time work.
ZoneId zone = ZoneId.of("America/Boise");
ZonedDateTime zdt1 = ZonedDateTime.of(2020, 12, 26, 22, 0, 0, 0, zone);
ZonedDateTime zdt2 = ZonedDateTime.of(2020, 12, 27, 1, 0, 0, 0, zone);
Duration fullElapsedTime = Duration.between(zdt1, zdt2);
Duration twoThirds = fullElapsedTime.multipliedBy(2).dividedBy(3);
ZonedDateTime lastThird = zdt1.plus(twoThirds);
System.out.println(lastThird);
Output from this snippet is:
2020-12-27T00:00-07:00[America/Boise]
Three things I like about this code are:
It pretty well mimics the way one would do the calculation by hand and how you would explain to someone else which calculation you want at all.
It takes any transistion to or from summer time (DST) into account.
It leaves the actual calculation to the library methods. It involves no low-level addition or division in your own code.
Link
Oracle tutorial: Date Time explaining how to use java.time.
One way to do this is the following:
Date midpoint = new Date((date1.getTime() + 2 * date2.getTime()) / 3);
If you insist using Date.
It should be a simple math:
First, need to calculate the difference between the two dates (in milliseconds).
Then get the 2/3 rd of that value and add it to the first date.
private static Date calculateLastThird(Date d1, Date d2) {
// Calculate time difference in milliseconds
long differenceMillis = d2.getTime() - d1.getTime();
double millisToAdd = (2.0/3.0) * differenceMillis;
Date twoThird = new Date(d1.getTime() + (long) millisToAdd);
return twoThird;
}
public static void main(String args[]) {
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
try {
Date date1= sdf1.parse("2020/12/26 22:00:00");
Date date2= sdf1.parse("2020/12/27 01:00:00");
SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm");
System.out.println("Last third: " + sdf2.format(calculateLastThird(date1, date2)));
Date date3= sdf1.parse("2020/12/26 22:25:00");
Date date4= sdf1.parse("2020/12/27 01:45:00");
System.out.println("Last third: " + sdf2.format(calculateLastThird(date3, date4)));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Sample output of above code:
Last third: 00:00
Last third: 00:38
This question already has an answer here:
Difference in time - from before midnight to after midnight without date
(1 answer)
Closed 3 years ago.
i need java code to find difference between two times in 24 hour format
for example:
20:00:00 - 04:00:00
and the expected output is 8 hrs
but now output is 16 hrs
when i tried 12 hour format out put is coming 4.
below is the code used to parse and to find difference
SimpleDateFormat readFormat = new SimpleDateFormat("HH:mm");
Date d1 = readFormat.parse(txtshiftIn);
Date d2 = readFormat.parse(txtshiftOut);
long diff = d2.getTime() - d1.getTime();
input is just 20:00 and 04:00 no seconds and AM/PM part.
The issue with using Date is it still expects an actual date even though you are using just the time portion of it, so if you're just sending it the time it will not be correct.
Instead use LocalTime and ChronoUnit.HOURS to get the difference between the time.
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
LocalTime lt1 = LocalTime.parse(txtshiftIn, dtf);
LocalTime lt2 = LocalTime.parse(txtshiftOut, dtf);
long diff = ChronoUnit.HOURS.between(lt1, lt2);
This will show -16 which means that lt1 is ahead of lt2 which indicates lt2 is the next day so we can modify it to get the differences as such
if (diff < 0) {
diff += 24;
}
This will give you the 8 hour difference you're expecting.
UPDATE
To account the difference in minutes you can do the following:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
LocalTime lt1 = LocalTime.parse(txtshiftIn, dtf);
LocalTime lt2 = LocalTime.parse(txtshiftOut, dtf);
long diff = ChronoUnit.MINUTES.between(lt1, lt2); //get diff in minutes
if (lt2.isBefore(lt1)) {
diff += TimeUnit.DAYS.toMinutes(1); //add a day to account for day diff
}
long hours = diff / 60;
long minutes = diff % 60;
LocalTime newTime = LocalTime.parse(String.format("%02d:%02d", hours, minutes), dtf); //Format the difference to be converted to LocalTime
System.out.println(newTime);
This will produce the difference in minutes:
08:30
Update 2
Here is a cleaner method that returns a Duration
public Duration timeDifference(String txtshiftIn, String txtshiftOut) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
LocalTime lt1 = LocalTime.parse(txtshiftIn, dtf);
LocalTime lt2 = LocalTime.parse(txtshiftOut, dtf);
Duration between = Duration.between(lt1, lt2);
if (lt2.isBefore(lt1)) { //account for lt2 being on the next day
between = Duration.ofMinutes(TimeUnit.DAYS.toMinutes(1)).plus(between);
}
return between;
}
While it is strongly recommended you use a more up-to-date Java time library like LocalTime your logic so far actually is correct with one little caveat:
SimpleDateFormat readFormat = new SimpleDateFormat("HH:mm");
Date d1 = readFormat.parse(txtshiftIn);
Date d2 = readFormat.parse(txtshiftOut);
long diff = d2.getTime() - d1.getTime();
In your code if d1 is after d2 you will get a negativ result for long diff
So when you say
"but now output is 16 hrs"
The actual output is -16 hrs
Of course minus sixteen hours doesn't make much sense in your case, but you can easily fix that with the simple trick of just adding 24 hours in case of a negative result for diff. (And -16+24 is the 8 you expected as a result).
So just add the following lines at the end of your posted code
if(diff < 0) {
diff = 86400000 + diff;
}
And you will get the results you expect!
(86400000 is the 24h expressed in milliseconds)
I want to calculate Relatives Date which is how many days different from 01/01/1957 to a given date. I need handle Daylight saving at the same time. Here is the code:
public String convertToRelative(String endDate) throws ParseException {
String relativeDate;
String baseDate = "19570101";
boolean isDST = TimeZone.getDefault().inDaylightTime(new java.util.Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Calendar cal = Calendar.getInstance();
cal.setTime(sdf.parse(baseDate));
long time1 = cal.getTimeInMillis();
cal.setTime(sdf.parse(endDate));
long time2 = cal.getTimeInMillis();
if ( isDST ) {
long between_days = (time2 - time1 - 3600000)/(1000*3600*24);
int relative = Integer.parseInt(String.valueOf(between_days));
relativeDate = String.valueOf(relative + 1);
} else {
long between_days = (time2 - time1)/(1000*3600*24);
int relative = Integer.parseInt(String.valueOf(between_days));
relativeDate = String.valueOf(relative + 1);
}
return relativeDate;
}
From the code, you can see I checked if the time is in daylight saving at:
boolean isDST = TimeZone.getDefault().inDaylightTime(new java.util.Date());
But it only gets default time from the system. My question is how can I check the given date is a daylight saving date first then do the calculation part. I'm using New Zealand time zone. Thank you.
Rather than doing the calculations manually, you should try to take advantage of the built-in API of java.time which are easy to use and take care of DST for you.
Refer : https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html#until-java.time.temporal.Temporal-java.time.temporal.TemporalUnit-
The following code should help you with calculations you are trying to do:
ZoneId auckZone = ZoneId.of("Pacific/Auckland");
LocalDateTime base = LocalDate.of(1957, 01, 01).atStartOfDay();
ZonedDateTime baseDate = base.atZone(auckZone);
ZonedDateTime endDate = LocalDate.parse(endDt, DateTimeFormatter.ofPattern("yyyyMMdd")).atStartOfDay().atZone(auckZone);
System.out.println(baseDate.until(endDate, ChronoUnit.DAYS));
I am having java.sql.date and java.sql.time objects, I need to find the time duration between the dates.
So i am creating java.sql.timestamp object by using above date and time object
Timestamp timestamp1 = new Timestamp(StartDate.getYear(),
StartDate.getMonth(), StartDate.getDay(),
StartTime.getHours(), StartTime.getMinutes(), 00,
00);
Here is mycode
String date = "2010-01-05";
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date3 = null;
try {
date3 = sdf1.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
Date StartDate = new Date(date3.getTime());
System.out.println("Date " + StartDate);
String date2 = "2010-01-06";
java.util.Date date4 = null;
try {
date4 = sdf1.parse(date2);
} catch (ParseException exception) {
exception.printStackTrace();
}
Date EndDate = new Date(date4.getTime());
System.out.println("Date " + EndDate);
String time = "01:00";
DateFormat formatter = new SimpleDateFormat("HH:mm");
java.sql.Time StartTime = null;
try {
StartTime = new java.sql.Time(formatter.parse(time).getTime());
} catch (ParseException exception2) {
exception2.printStackTrace();
}
System.out.println("TIMEEEEEEEEEE====" + StartTime);
String time2 = "02:00";
java.sql.Time EndTime = null;
try {
EndTime = new java.sql.Time(formatter.parse(time2).getTime());
} catch (ParseException exception3) {
exception3.printStackTrace();
}
System.out.println("TIMEEEEEEEEEE====" + EndTime);
Timestamp timestamp1 = new Timestamp(StartDate.getYear(),
StartDate.getMonth(), StartDate.getDay(),
StartTime.getHours(), StartTime.getMinutes(), 00,
00);
Timestamp timestamp2 = new Timestamp(EndDate.getYear(),
EndDate.getMonth(), EndDate.getDay(),
EndTime.getHours(), EndTime.getMinutes(), 00, 00);
long milliseconds = timestamp2.getTime() - timestamp1.getTime();
int seconds = (int) milliseconds / 1000;
// calculate hours minutes and seconds
int hours = seconds / 3600;
int minutes = (seconds % 3600) / 60;
seconds = (seconds % 3600) % 60;
System.out.println(hours+"h:"+minutes+"m:"+"00s");
Test case
when I give date as 2010-01-05 and date2 as 2010-01-06 I am getting output as below
Date 2010-01-05
Date 2010-01-06
TIMEEEEEEEEEE====01:00:00
TIMEEEEEEEEEE====02:00:00
25h:0m:00s
when I give date as 2010-01-05 and date2 as 2010-01-11 I am getting output in negative value as below
Date 2010-01-05
Date 2010-01-11
TIMEEEEEEEEEE====01:00:00
TIMEEEEEEEEEE====02:00:00
-23h:0m:00s
Help me to correct if I am doing something wrong.
Thanks in advance.
Manual time calculation:-
Converts Date in milliseconds (ms) and calculate the differences between two dates, with following rules :
1000 milliseconds = 1 second
60 seconds = 1 minute
60 minutes = 1 hour
24 hours = 1 day
Sample Example:-
package com.dps2.practice.dyuti;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDifferentExample {
public static void main(String[] args) {
String dateStart = "08/11/2016 09:29:58";
String dateStop = "08/12/2016 10:31:48";
//HH converts hour in 24 hours format (0-23), day calculation
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
//in milliseconds
long diff = d2.getTime() - d1.getTime();
long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.print(diffDays + " days, ");
System.out.print(diffHours + " hours, ");
System.out.print(diffMinutes + " minutes, ");
System.out.print(diffSeconds + " seconds.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
The problem with your calculation is this: StartDate.getDay() etc.
getDay() will return the number of day of the week (read the JavaDoc) and not the day of the month. You'll need to use getDate() instead.
To illustrate the problem using your values: 2010-01-05 will return 2 for getDay() and thus you are getting 2010-01-02 as your timestamp. 2010-01-11 will return 1 for getDay() (it's 6 days later, i.e. (2 + 6) % 7 = 1) and hence your second timestamp becomes 2010-01-01. Now the second timestamp is before the first and hence you get a negative value.
However, as I already stated in my comments you should try and use some library or at least the non-deprecated built-in functionality for those calculations to save you a lot of headaches (I suggest you watch this video to get an idea of the challenges: https://youtube.com/watch?v=-5wpm-gesOY ).
The java.sql date-time classes are meant only for exchanging data with databases. Do not use them for business logic. Also, they are part of the troublesome, poorly designed, and confusing old legacy date-time classes. Avoid them all.
java.time
The java.time classes built into Java 8 and later supplant the old classes you are using. Much simpler now.
LocalDate ld = LocalDate.parse ( "2010-01-06" );
LocalTime lt = LocalTime.parse ( "01:00" );
LocalDateTime earlier = LocalDateTime.of ( ld , lt );
LocalDateTime later = earlier.plusHours ( 7 );
The Duration class represents a span of time as a total number of seconds and nanoseconds. Its toString method generates a String in the standard ISO 8601 format PnYnMnDTnHnMnS. This format uses P to mark the beginning, and the T to separate year-months-days from hours-minutes-seconds portion. The Duration and Period classes can both parse and generate such Strings.
Duration duration = Duration.between ( earlier , later );
In Java 8, Duration class inexplicably lacks getter methods for each part: days, hours, minutes, seconds, fraction-of-second. Java 9 rectifies this omission with new getPart methods.
Dump to console.
System.out.println ( "earlier: " + earlier + " | later: " + later + " | duration: " + duration );
earlier: 2010-01-06T01:00 | later: 2010-01-06T08:00 | duration: PT7H
Time zone
Be aware that your inputs lacked any information about offset-from-UTC or time zone. So the math seen above is performed assuming generic 24-hour days. Real-world anomalies such as Daylight Saving Time (DST) are ignored.
If you did indeed intend time zones, assign them via the atZone method to instantiate OffsetDateTime or ZonedDateTime objects.
That's a complicated code you have in your question there. You can make it quite easy by using java.util.concurrent.TimeUnit class.
Output
Date Tue Jan 05 00:00:00 UTC 2010
Date Wed Jan 06 00:00:00 UTC 2010
difference is:
24 hours : 1440 minutes : 86400 seconds
Code
import java.util.*;
import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;
public class HelloWorld {
public static void main(String[] args) {
String date = "2010-01-05";
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date3 = null;
try {
date3 = sdf1.parse(date);
} catch (Exception e) {
e.printStackTrace();
}
Date StartDate = new Date(date3.getTime());
System.out.println("Date " + StartDate);
String date2 = "2010-01-06";
java.util.Date date4 = null;
try {
date4 = sdf1.parse(date2);
} catch (Exception exception) {
exception.printStackTrace();
}
Date EndDate = new Date(date4.getTime());
System.out.println("Date " + EndDate);
long dateStart = StartDate.getTime(), dateStop = EndDate.getTime();
long diff = dateStop - dateStart;
long diffInSeconds = TimeUnit.MILLISECONDS.toSeconds(diff);
long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(diff);
long diffInHours = TimeUnit.MILLISECONDS.toHours(diff);
System.out.println("\n\ndifference is:\n");
System.out.println(diffInHours + " hours : " + diffInMinutes + " minutes : " + diffInSeconds + " seconds");
}
}
Probably there will be simply and fast answer but I still cant find out why is the result of
Date date = new Date(60000); //one min.
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
String dateStr = dateFormat.format(date);
dateStr - 01:01:00
Still one hour more. Time zone? How can I set it without it? Thanks.
Date represents a specific moment in time, not a duration. new Date(60000) does not create "one minute". See the docs for that constructor:
Initializes this Date instance using the specified millisecond value. The value is the number of milliseconds since Jan. 1, 1970 GMT.
If you want "one minute from now" you'll probably want to use the Calendar class instead, specifically the add method.
Update:
DateUtils has some useful methods that you might find useful. If you want the elapsed time in HH:mm:ss format, you might try DateUtils.formatElapsedTime. Something like:
String dateStr = DateUtils.formatElapsedTime(60);
Note that the 60 is in seconds.
Three ways to use java.util.Date to specify one minute:
1. Using SimpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")) as shahtapa said:
Date date = new Date(60*1000); //one min.
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateStr = dateFormat.format(date);
System.out.println("Result = " + dateStr); //Result should be 00:01:00
2. Using java.util.Calendar as kabuko said:
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(Calendar.MINUTE,1); //one min.
Date date = calendar.getTime();
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
String dateStr = dateFormat.format(date);
System.out.println("Result = " + dateStr); //Result should be 00:01:00
Other calendar.set() statements can also be used:
calendar.set(Calendar.MILLISECOND,60*1000); //one min.
calendar.set(1970,0,1,0,1,0); //one min.
3. Using these setTimeZone and Calendar ideas and forcing Calendar to
UTC Time-Zone
as Simon Nickerson said:
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
calendar.clear();
calendar.set(Calendar.MINUTE,1); //one min.
Date date = calendar.getTime();
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateStr = dateFormat.format(date);
System.out.println("Result = " + dateStr); //Result should be 00:01:00
Note: I had a similar issue: Date 1970-01-01 was in my case -3 600 000 milliseconds (1 hour late) java.util.Date(70,0,1).getTime() -> -3600000
I recommend to use TimeUnit
"A TimeUnit represents time durations at a given unit of granularity and provides utility methods to convert across units, and to perform timing and delay operations in these units. A TimeUnit does not maintain time information, but only helps organize and use time representations that may be maintained separately across various contexts. A nanosecond is defined as one thousandth of a microsecond, a microsecond as one thousandth of a millisecond, a millisecond as one thousandth of a second, a minute as sixty seconds, an hour as sixty minutes, and a day as twenty four hours."
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/TimeUnit.html
Date date = new Date(); // getting actual date
date = new Date (d.getTime() + TimeUnit.MINUTES.toMillis(1)); // adding one minute to the date