I am trying to write function to find day difference between two date it work ok but the result change some time in the same inputs .Let say the current date is 21/7/2014 the result some time is 567 and other time 566.
The code:
//TO GET THE CURRENT DATE
Calendar cal = Calendar.getInstance();
//THE CAL.ADD BECUSE THE 1ST MONTH IN THE YEAR IS 0 NOT 1
cal.add(Calendar.MONTH, 1);
//TO SET THE START DATE WICH IS 1/1/2013
Calendar startDate=Calendar.getInstance();
startDate.set(Calendar.DAY_OF_MONTH, 1);
startDate.set(Calendar.MONTH,1);
startDate.set(Calendar.YEAR, 2013);
//TO FIND THE DIFF BETWEEN THE START DATE AND CUREENT DATE , THE +1 BECUSE IT IS
ALWAYS LESS BY ONE DAY
long diff=(((cal.getTimeInMillis()-
startDate.getTimeInMillis())/(1000*60*60*24))+1);
I think this is because of the hours which get rounded in a strange way..
On my side when I add the following code it seems to work fine:
cal.set(Calendar.HOUR_OF_DAY, 1);
startDate.set(Calendar.HOUR_OF_DAY, 1);
The problem here is when you are instantiating a calendar, you are getting current date and time. So when you ignore time values it works perfectly.
Two compare two dates it's better to use Date class and java and use the following code
So your above code can be rewritten as
Date cal = new Date(114, 7, 21); //Date is 21/7/2014
Date startDate = new Date(113, 1, 1); Date is 1/1/2013
long newdiff = ((cal.getTime()-startDate.getTime())/(1000*60*60*24));
System.out.println(newdiff);
This time it will print 566 correctly (The actuall difference is 566)
The problem really is that suppose you are comparing today's date and tomorrow'date.
ie 21/7/2014 and 22/7/2014. The difference in days is one. If you run the program at 12:00 am midnight you will get 1. and at any other time after that it will result in 0. This is because of getting current time along with the date
Related
I mentioned that one of the method in the production project work wrong with dates, but i can't just replace it, because it is in production for a long time. I've created a new method, that works correct, but i can't figure out why the first method work wrong.
Old method (that works wrong):
public static Integer getNumberOfDays(Date startDate, Date endDate) {
TimeZone.setDefault((TimeZone.getTimeZone("Europe/Moscow")));
startDate.setHours(00);
startDate.setMinutes(00);
startDate.setSeconds(00);
endDate.setHours(23);
endDate.setMinutes(59);
endDate.setSeconds(59);
Calendar cal1 = Calendar.getInstance();
cal1.setTime(startDate);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(endDate);
Calendar date = (Calendar) cal1.clone();
int daysBetween = 0;
while (date.before(cal2)){
date.add(Calendar.DAY_OF_MONTH, 1);
daysBetween++;
}
return daysBetween;
}
New method:
public static Integer getNumberOfDaysSecondVersion(Date startDate, Date endDate) {
long difference = startDate.getTime() - endDate.getTime();
float daysBetween = (difference / (1000*60*60*24));
return (int) daysBetween > 0 ? (int) daysBetween : 0;
}
Here is how i call both:
DateFormat formated = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(Calculation.getNumberOfDays(
formated.parse("2018-06-14"),
formated.parse("2018-06-06")
));
System.out.println(Calculation.getNumberOfDaysSecondVersion(
format.parse("2018-06-14"),
format.parse("2018-06-06"))
);
Output:
0
8
Please help.
Your old method is the correct one. When start date is after end date, it returns 0. This is the case in your call.
Your new method subtracts end date from start date, which is wrong, is should be the other way around. I also suspect that it will give surprises across transitions from and to summer time (DST). While Moscow currently doesn’t use summer time, it has done historically, at least until 2010, and may do again if politicians decide so.
That said, you should try if you can avoid the old and long outdated date and time classes DateFormat, SimpleDateFormat, Calendar, Date and TimeZone. Today we have so much better in java.time, the modern Java date and time API. Of course, in legacy code you have old-fashioned Date objects. When writing a new method, I recommend you convert those to the modern LocalDate and use ChronoUnit.DAYS.between().
ChronoUnit.DAYS.between(
LocalDate.parse( "2018-06-14" ) ,
LocalDate.parse( "2018-06-06" )
)
-8
Be aware that when the old method sets the default time zone, it affects all programs running in your JVM and may come as a nasty surprise to other parts of your program and to other programs.
You used a very different algorithm for the two versions.
The old version keeps adding days to the start date until it is after the end date.
The new version subtracts the end date from the start date and divides it by the number of milliseconds there are in a day.
This means that for the first version to work, the start date must be before the end date, and for the second version to work, the start date must be after the end date. The parameters you gave the the first version has the start date after the end date, making it return 0.
To fix this, you can just reverse the two arguments:
System.out.println(getNumberOfDays(
formated.parse("2018-06-06"),
formated.parse("2018-06-14")
));
Or, check which date comes first before calculating the difference between them.
By the way, your first version seems to output one more than your second version. You seem to want a result of 8 days. This means that your first version has an off-by-1 error. You can fix this by subtracting 1 from the counted result.
Remember to always work with java.time whenever you can!
Probably because startDate and endDate's timezones aren't affected by setting the default timezone, so that when you set Calendar times (in Moscow time) based on them, you're converting timezones, possibly turning 00:00:00 into the previous day 21:00:00 or something.
EDIT
Seeing your outputs, it became obvious... you're passing in a start date that is in the future compared to end date. The original method uses a loop that can only count up, while your new method takes the absolute value of the difference.
I have function which calculated time difference between two dates in milliseconds. I am getting the time just before 1 hour of day light saving starts and then calculating time after 5 minutes of it. I is giving me 5 minutes of difference, One hour getting skipped. Do anyone having idea?
Just use this:
Suppose date1 is 20.03.2016, 13:00
date2 is 21.03.2016, 17:00
Calendar cal1 = Calendar.getInstance();
cal1.set(Hour_of_day,13);
cal1.set(Calendar.DAY_OF_MONTH, 20);
Calendar cal2 = Calendar.getInstance();
cal2.set(Hour_of_day,17);
cal2.set(Calendar.DAY_OF_MONTH, 21);
then difference of two gives time in milliseconds.
long time_in_milli = cal2.getTimeInMillis()-cal1.getTimeInMillis();
This would already take into account the day light saving thing.
I solved this by including timezone with date ex: Format your date with timezone like - "yyyy-MM-dd'T'HH:mm:ss.SSSZ" and then calculate time difference.
I have tried all the ways in all the other questions on SO, and I can't get it to work. It is making me want to kill myself.
I have a set of times which are something like "04:00 AM AEST", except the AEST is a glitch, they should be GMT. What I want to do is change them to "04:00 GMT", and then convert them up to the correct AEST times (which in this example would be "14:00 AEST"). I have tried everything, and nothing works. The closest was to manually make a new DateTime using each individual value from the original date, e.g.
DateTime dt = new DateTime(origdate.year, origdate.month, origdate.day, origdate.hour, origdate.minute, origdate.second, timezone.GMT)
But for some reason the results came out four and a half minutes over, which is weird because timezones differ on hours and half hours.
1st Method By following lines you will get GMT time in specified format :
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Date currentLocalTime = cal.getTime();
DateFormat date = new SimpleDateFormat("dd-MM-yyy HH:mm:ss z");
date.setTimeZone(TimeZone.getTimeZone("GMT"));
String gmtTime = date.format(currentLocalTime);
Hence, from GMT you can derive the time of any place.
2nd Method You can get system time of current place in milliseconds by:
Long current_time = System.currentTimeMillis() / 1000L;
Hope it helps.
I'm having trouble with the format method of a SimpleDateFormat object.
The code in question is:
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(date);
Where "date" is a Date object created using a long int from Calendar.getTimeInMillis();
Calendar cal = Calendar.getInstance();
Date date = new Date(cal.getTimeInMillis());
Everything is working fine except the year portion of the string. When I pass the date, the string outputted looks like this:
0044-09-10 05:30:24
The date object that is passed is created from a long integer returned from:
Calendar.getTimeInMillis();
I believe the number returned from this method counts the milliseconds from Jan. 1st. 1970, which I'm thinking is the problem, but even if I add the number of milliseconds in 1970 years (lol, probably the wrong thing to do, but it was worth a shot :P), it still parses as 0044 in the year portion.
I've done numerous google searches and all seem to point simple issues in the string passed to the SimpleDateFormat constructor, so I'm at a loss here.
Any help is greatly appreciated.
Please let me know if any other information is needed and I will do my best to provide it.
Thanks again!
EDIT:
I figured I would explain the context a little more:
A technician will run a call, and on arriving to the site, will mark the call as "Started."
The app will then create a Calendar instance and save the long int returned from Calendar.getTimeInMillis().
When the technician is finished with the call, he/she will mark the call as "Complete." Again, a Calendar instance is created and the long int returned from Calendar.getTimeInMillis() is saved.
This allows easy "call duration" calculation.
Now, when the closing form that the technician uses in the app is used, the long ints saved during the calls is passed to a Date object, which is then passed to a SimpleDateFormat.format() method.
This is where the issue arises. Thanks again, hope this helped.
To calculate duration between date/times, don't rely on subtracting milliseconds, it is highly unreliable.
If you're using Java 8, you should take advantage of the new java.time API, for example...
LocalDateTime dt1 = LocalDateTime.of(2014, 9, 11, 10, 0);
LocalDateTime dt2 = LocalDateTime.of(2014, 9, 11, 12, 0);
Duration duration = Duration.between(dt1, dt2);
System.out.println(duration.toDays());
System.out.println(duration.toHours());
System.out.println(duration.toMinutes());
System.out.println(duration.getSeconds());
Which outputs...
0
2
120
7200
Take a look at Period and Duration for more details.
Alternatively, you could use JodaTime (which the java.time is based off)
The time that the Calendar.getTimeinMillis() returns is the millisecond since the "epoch" time. Consulting the javadoc for Date class, you can find that the "epoch" is January 1, 1970, 00:00:00 GMT. Thus, you code should be fine. I have tested with following code:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class Cal {
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
Date date = new Date(cal.getTimeInMillis());
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(date);
System.out.println(date);
}
}
And it gives a correct output:
Thu Sep 11 09:48:30 KST 2014
One think I'd like to mention is the 'call duration' is not a date. If you are trying to convert the result of the subtraction between two long value into a Date object, It will fail because the subtraction will eliminate the since-the-epoch part of the time from the long value. The result of the subtraction is just a millisecond.
Okay, I have solved the issue. It turns out I did not include enough information for everyone to correctly figure out this issue.
In the app, I use two pickers, one for date, and one for time, when saving the date, it saves the date selected, with the time set at 00:00:00 and coverts that to a long int in milliseconds.
using:
Calendar cal = Calendar.getInstance();
cal.set(year, month, day);
When saving the time it saves the time selected using the same method, but when I was calling cal.set() I was setting the year, month, and day, to 0.
i.e.
cal.set(0, 0, 0, hour, minute, second);
changing this statement to
cal.set(1970, 0, 1, hour, minute, second);
fixed the issue. My apologies for wasting everyone's time as this was simply a logical mistake on my part..
I sincerely appreciate all the help provided.
I am getting the time in seconds from a function and I have to move further it into days and from the date 2/11/1970 00:00:00 till time in seconds I am getting will be covered. Please help me how to achieve this, or help me to do calculation on dates.
Not sure if I quite get your question, but if I do, have you tried the Calendar object?
Here's an example of how you could get the day out of the time in milliseconds:
Calendar cal = Calendar.getInstance();
Date date = new Date();
cal.setTimeInMillis(date.getTime());
int dayOfYear = cal.get(Calendar.DAY_OF_YEAR);
Take a look at the Joda date time API. IT should cater for your needs. This should point you in the right direction.