I am trying to calculate the number of days between two dates.
First case :
String string = "01/03/2014";
Date dateFin = new SimpleDateFormat("dd/MM/yyyy", Locale.FRANCE).parse(string);
string = "31/03/2014";
Date dateDebut = new SimpleDateFormat("dd/MM/yyyy", Locale.FRANCE).parse(string);
long result = Math.abs(dateFin.getTime() - dateDebut.getTime());
System.out.println((int) (result / (long) (1000 * 3600 * 24)));
=> Result :
29
Second case :
String string = "01/03/2013";
Date dateFin = new SimpleDateFormat("dd/MM/yyyy", Locale.FRANCE).parse(string);
string = "31/03/2013";
Date dateDebut = new SimpleDateFormat("dd/MM/yyyy", Locale.FRANCE).parse(string);
long result = Math.abs(dateFin.getTime() - dateDebut.getTime());
System.out.println((int) (result / (long) (1000 * 3600 * 24)));
=> Result :
30
Question:
Why there is a difference between this two cases?
Thanks
The value in result is one hour less than the exact 24*30 hours. If you add 3600000 (that is 1 hour) to result, you will get the exact 24 hours (expressed in milliseconds). Apparently in France they change clocks from Winter to Summer time in the month of March. So in March there are 24*30 - 1 hours, not 24 hours. This explains why you don't have the same problem when you try the two May dates. This is my best explanation based on what I'm seeing.
See also:
http://timeanddate.com/time/change/france/paris?year=2013
http://timeanddate.com/time/change/france/paris?year=2014
You are parsing 31/03/2013 (i.e. 00:00 AM). The clock change didn't happen
until 31/03/2013, 02:00 AM. So in 2013 you have the exact 30*24 hours in March,
while in 2014 you have 1 hour less as the change happened on 3/30/2014.
Related
I'm working on simple countdown app to tell me how long until certain GMT time.
example:
input: 01-05-2021-02-00-00
output: (if entered time is local) 72 days, 15 hours, 21 mins, 49 secs
output(if entered time is gmt): 72 days, 17 hours, 21 mins, 33 secs
...there should be 16 not 17 hours i believe.
Everything's working fine untill input is between 1. April and 31 October. I give it GMT time and it transforms it to my local (berlin +1) time. If entered time is from mentioned interval it shows +2 hours differencer between berlin and GMT. since it is like this only for certain period of year (any year) it looks weird I don't know what went wrong?
my code:
String result = "";
String date = input;
SimpleDateFormat date_format = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
Date target_date = null;
try {
target_date = date_format.parse(date);
} catch (ParseException e) {
result += e.getMessage();
}
Date now = new Date();
long secs = 0;
if(local_time_radio_btn.isSelected()) {
secs = (target_date.getTime() - now.getTime()) / 1000;
}else {
int offset = target_date.getTimezoneOffset();
long n = 1000 * offset * 60;
long gmt = target_date.getTime() -n;
long now_gmt = now.getTime();
secs = (gmt - now_gmt) / 1000;
}
long days = secs / (60*60*24);
secs = secs % (60*60*24);
long hours = secs / (60*60);
secs = secs % (60*60);
long mins = secs / 60;
secs = secs % 60;
result += days+" days, "+hours+" hours, "+mins+" mins, "+secs +" secs";
java.time
I strongly recommend that you use java.time, the modern Java date and time API, for your date and time work.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-uuuu-HH-mm-ss");
String input = "01-05-2021-02-00-00";
LocalDateTime targetLdt = LocalDateTime.parse(input, formatter);
// German time case
ZoneId zone = ZoneId.of("Europe/Berlin");
ZonedDateTime now = ZonedDateTime.now(zone);
ZonedDateTime target = targetLdt.atZone(zone);
long days = ChronoUnit.DAYS.between(now, target);
ZonedDateTime afterDays = now.plusDays(days);
Duration timeDiff = Duration.between(afterDays, target);
String result = days + " days, " + timeDiff.toHours() + " hours, "
+ timeDiff.toMinutesPart() + " mins, "
+ timeDiff.toSecondsPart() + " secs";
System.out.println(result);
When I ran the code just now (2021-02-18T17:23:35.47 in Berlin), the output was:
71 days, 8 hours, 36 mins, 24 secs
For the UTC (or GMT) case you only need to change one line:
// GMT case
ZoneId zone = ZoneOffset.UTC;
71 days, 9 hours, 36 mins, 24 secs
What went wrong in your code?
First, don’t use SimpleDateFormat and Date as they are poorly designed and long outdated. Even if you insisted on using Date, you should definitely stay away from its getTimezoneOffset method. It has been deprecated since 1997 because it works unreliably across time zones.
Why your code gives an incorrect result in the months you mention is that it counts a day as always 24 hours. On March 28 the EU will transit to summer time (DST), so that day is only 23 hours long, giving rise to an error of exactly 1 hour. On October 31 this year the opposite transisiton may happen (I don’t think it’s been decided yet, but Java thinks that it does), so that day is 25 hours, balancing out for dates after that. Until summer time next year.
Which leads to the next point: don’t do time math yourself. It’s so easy to get wrong. And even when you get it right, it’s hard for the reader to convince oneself that it’s right. You have got a reliable date and time library that is happy to do it for you.
Link
Oracle tutorial: Date Time explaining how to use java.time.
What's weird about your code is that you're first parsing the input string according to a SimpleDateFormat instance that's configured to use local timezone (so, the resulting Date is wrong if the input was meant to be UTC), and then put a lot of effort into re-adjusting the point in time to UTC if that's what the user requested.
Instead, it would be clearer and more robust to have two SimpleDateFormat instances, one with the local timezone, and one with UTC, like:
SimpleDateFormat dateFormatLocal = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
SimpleDateFormat dateFormatUTC = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
dateFormatUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
and select the correct one already when parsing.
By the way, your re-adjusting code uses deprecated features of the Date class, like getTimezoneOffset(), something that should be avoided since Java 1.1.
I have a misundertood managing dates in Java when I want to calculate the span in number of days between two dates.
Say we have two different dates:
Date 1: 1986-01-24
Date 2: 2017-04-20
Case 1: I have this snippet of code using Dates:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date dt1 = format.parse("1986-01-24");
Date dt2 = format.parse("2017-04-20");
int intSpanInDays= (int) ((dt2.getTime() - dt1.getTime()) / (1000 * 60 * 60 * 24));
System.out.println("Days between: " + intSpanInDays);
Output 1:
Days between: 11408
Case 2: Snippet of code using Calendar:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
GregorianCalendar cal1 = new GregorianCalendar();
cal1.setTime(format.parse("1986-01-24"));
cal1.set(Calendar.HOUR, 0);
cal1.set(Calendar.MINUTE, 0);
cal1.set(Calendar.SECOND, 0);
GregorianCalendar cal2 = new GregorianCalendar();
cal2.setTime(format.parse("2017-04-20"));
cal2.set(Calendar.HOUR, 0);
cal2.set(Calendar.MINUTE, 0);
cal2.set(Calendar.SECOND, 0);
long spanInMillis = cal2.getTimeInMillis() - cal1.getTimeInMillis();
GregorianCalendar cal3 = new GregorianCalendar();
cal3.setTimeInMillis(spanInMillis);
long millisInADay = 1000 * 60 * 60 * 24;
System.out.println("Days between: " + (cal3.getTimeInMillis() / millisInADay));
Output 2:
Days between: 11408
Case 3: Example using a spreadsheet in Excel:
When I use MS Excel to get this span just introducing the given dates and simply substracting, the output is this:
QUESTION
Why is Java calculation code of date missing one day? What is missing or wrong in either case 1 and 2 that does not match the result in case 3?
The spreadsheet is taking Daylight Savings into account, and your calculations are naively truncating, and given that there's one more 23-hour day in the interval than 25-hour days, the 23-hour remainder is truncated, yielding a result one day less than the correct answer.
JDK 8 largely simplifies these calculations with its new date time API. The same can be done accurately and simply using the below code :
LocalDate date1 = LocalDate.of(1986, 01, 24);
LocalDate date2 = LocalDate.of(2017, 04, 20);
System.out.println(date1.until(date2, ChronoUnit.DAYS));
This automatically takes care of any/all the DST changes, leap years etc. which is mostly missed when trying to do the calculations manually.
This question already has answers here:
Calculating the difference between two Java date instances
(45 answers)
Closed 7 years ago.
Im trying to calculate the time difference between 2 Timestamps, this is the code:
Calendar calendar = Calendar.getInstance();
java.util.Date now = calendar.getTime();
Timestamp currentTimestamp = new Timestamp(now.getTime());
System.out.println("Current\n"+currentTimestamp);
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
Date date = dateFormat.parse("28/02/2015");
Timestamp timestampBefore = new Timestamp(date.getTime());
System.out.println("Before\n"+timestampBefore);
Timestamp calculated = new Timestamp(currentTimestamp.getTime() - timestampBefore.getTime());
System.out.println("Calculated\n"+calculated);
Output:
Current
2015-02-28 12:12:40.975
Before
2015-02-28 00:00:00.0
Calculated
1970-01-01 13:12:40.975
I can understand why it returns 1970-01-01 but why does it return 13:12:40.975 ,1 hour more?
How to calculate the difference between 2 dates so the output is like this (based on this example):
Years:0, Months:0, Days:0, Hours:12, Minutes:12, Seconds:40 ?
Update: for java below 1.8 check out http://www.joda.org/joda-time/index.html
and for java 1.8 see answer.
Similar solution here: Java 8: Calculate difference between two LocalDateTime
(1) A timestamp is a point in time. If you calculate the difference between two timestamps, the result is not a timestamp (point in time), but a duration. So it is nonsense to convert the difference to a timestamp, hence it is useless to discuss the reason why the result is strange.
(2) You should probably use the new Java 8 time API (if you are able to use Java 8):
LocalTime now = LocalTime.now();
LocalTime previous = LocalTime.of(0, 0, 0, 0);
Duration duration = Duration.between(previous, now);
System.out.println(now);
System.out.println(previous);
System.out.println(duration);
Note that this just calculates the duration between two times of a day (hour-minute-second). If your want to include date information, use LocalDateTime instead:
LocalDateTime nextFirework = LocalDate.now()
.with(TemporalAdjusters.firstDayOfNextYear())
.atTime(LocalTime.MIDNIGHT);
LocalDateTime now = LocalDateTime.now();
// duration (in seconds and nanos)
Duration duration = Duration.between(now, nextFirework);
// duration in total hours
long hours = now.until(nextFirework, ChronoUnit.HOURS);
// equals to: duration.toHours();
If you want to have 'normalized' duration in years/months/days/hours/seconds, there is suprisingly no direct support. You could convert the duration to days, hours, minutes and seconds by yourself:
long d = duration.toDays();
long h = duration.toHours() - 24 * d;
long m = duration.toMinutes() - 60 * duration.toHours();
long s = duration.getSeconds() - 60 * duration.toMinutes();
System.out.println(d + "d " + h + "h " + m + "m " + s + "s ");
But note that you will have difficulties converting the days into months and years, as there is no unique number of days per month and a year can be a leap year with 366 days. For that, you can use Period, as in opposite to Duration, this class is associated with a timeline. Unfortunately, Period does only support dates, but no times:
// period in years/months/days (ignoring time information)
Period p = Period.between(now.toLocalDate(), nextFirework.toLocalDate());
System.out.println(p); // or use p.getYears(), p.getMonths(), p.getDays()
So probably you could combine both approaches - first, compute the Period from the dates and then the Duration using the times. Note that the duration can be negative, so you'll have to take care of that in case of:
Duration dur = Duration.between(start.toLocalTime(), end.toLocalTime());
LocalDate e = end.toLocalDate();
if (dur.isNegative()) {
dur = dur.plusDays(1);
e = e.minusDays(1);
}
Period per = Period.between(start.toLocalDate(), e);
System.out.println(per.toString() + ", " + dur.toString());
I've the following two dates in a string format and would like to get the elapsed time for those.
Date elapsed = new Date(
new SimpleDateFormat().parse("10/17/2014, 2:19:22 PM").getTime()
- new SimpleDateFormat().parse("10/17/2014, 2:19:32 PM").getTime());
System.out.println("Elapsed Time: " + elapsed);
However, I get ...ParseException: Unparseable date: "10/17/2014, 2:19:22 PM" does anyone know why?
Note: here is how I got the date you see in parse block generated new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time)
You have to specify format in SimpleDateFormat constructor.
Your String has format dd/MM/yyyy, hh:mm:ss a
Your logic of substraction is incorrect as it will give you the long value difference between dates and you are creating date from that value which is not valid.For that you have to get exact difference from that long value.You have to divide diff with (1000 * 60) to get minutes, (1000 * 60 * 60) to get Seconds and (1000 * 60 * 60 * 24) to get days.
SimpleDateFormat sdf= new SimpleDateFormat("dd/MM/yyyy, hh:mm:ss a");
long diff = sdf.parse("10/17/2014, 2:19:22 PM").getTime()
- sdf.parse("10/17/2014, 2:18:32 PM").getTime();
System.out.println("Difference : " + (diff / (1000d * 60 )) +" Minutes");
NOTE: 1000d is used to perform floating point arithmetic here.
However, I get ...ParseException: Unparseable date: "10/17/2014, 2:19:22 PM" does anyone know why?
Because you haven't told SimpleDateFormat what the format of the string will be. Use one of the constructor that accepts a pattern string so that it knows what to expect.
I am using unix timestamp to store the purchase date in my application.
sample data: 1371463066
I want to do some manipulation based on the difference in number of days and current day timestamp.
for example: If the number of days between the purchase date and current date is 5 days, then send an email regarding feedback again.
how to get the difference in days between two timestamps using java?
I have not tested it but you may try to do something like this:
Date purchasedDate = new Date ();
//multiply the timestampt with 1000 as java expects the time in milliseconds
purchasedDate.setTime((long)purchasedtime*1000);
Date currentDate = new Date ();
currentDate .setTime((long)currentTime*1000);
//To calculate the days difference between two dates
int diffInDays = (int)( (currentDate.getTime() - purchasedDate.getTime())
/ (1000 * 60 * 60 * 24) )
Unix timestamp is the number of seconds since 1.1.1970. If you have 2 unix timestamps then the difference in full days is
int diff = (ts1 - ts2) / 3600 / 24
You could try with Calendars (which will also allow you to use TimeZones):
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(1371427200l * 1000l);
Calendar newCalendar = Calendar.getInstance();
newCalendar.setTimeInMillis(1371527200l * 1000l);
// prints the difference in days between newCalendar and calendar
System.out.println(newCalendar.get(Calendar.DAY_OF_YEAR) - calendar.get(Calendar.DAY_OF_YEAR));
Output:
1