I want to calculate the sleeping time of user, he should enter when he slept and when he woke up and I should calculate how many hours he slept
For example if the user enter
His sleeping time : 11:00 pm
His waking up time : 7:30 am
The number of sleeping hours should be : 8:30 hrs
Is there any way to make this calculation easily
This is the code
cal.set(Calendar.HOUR_OF_DAY, 11);
cal.set(Calendar.MINUTE, 0);
sleepTimeOnOffDays = cal.getTime();
private long subtractTwoDates(Date date1, Date date2) {
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.setTime(date1);
calendar2.setTime(date2);
long milsecs1 = calendar1.getTimeInMillis();
long milsecs2 = calendar2.getTimeInMillis();
long diff = milsecs2 - milsecs1;
long dhours = diff / (60 * 60 * 1000);
return Math.abs(dhours);
}
From Java SE 8 onwards i would like to suggest using the java.time API. For Android users, java.time is added in API 26+.
Java 8 introduced new APIs for Date and Time to address the shortcomings of the older java.util.Date and java.util.Calendar.
Using the java.time API calculating the duration between 2 date times is very easy.
LocalDateTime localDateTime1 = LocalDateTime.now();
localDateTime1 = localDateTime1.withHour(23).withMinute(0).withSecond(0).withNano(0);
LocalDateTime localDateTime2 = LocalDateTime.now();
localDateTime2 = localDateTime2.plusDays(1).withHour(7).withMinute(30).withSecond(0).withNano(0);
Duration diff = Duration.between(localDateTime1, localDateTime2);
String hms = String.format("%d:%02d:%02d",
diff.toHoursPart(),
diff.toMinutesPart(),
diff.toSecondsPart());
System.out.println(hms);
-----------------------
Console output:
8:30:00
If the java.time API is not available for your project, because for example your project is not yet on API level 26, then i would recommend using the ThreeTen Android Backport API as suggested by #Ole V.V in the comments below.
The Syntax is pretty much the same as the java.time API. The code snippet above works for the ThreeTen Android Backport API as well (like #Basil Bourque already mentioned) with one exception. The Duration class of the ThreeTen Android Backport API unfortunately does not provide helper methods for extracting the hours part, minutes part etc. from the duration object. Instead when you use the backport you need to subtract first the hours, then the minutes from the duration so only the seconds are left:
long hours = diff.toHours();
diff = diff.minusHours(hours);
long minutes = diff.toMinutes();
diff = diff.minusMinutes(minutes);
long seconds = diff.getSeconds();
String hms = String.format("%d:%02d:%02d",
hours,
minutes,
seconds);
Another difference is you need to import the java.time classes from the org.threeten.bp package (not the java.time package).
If you want to use the ThreeTen Backport API, just include it's dependency to your project.
tl;dr
11:00 PM to 7:30 AM = 7.5 or 8.0 or 8.5 or 9.5 or some other number of hours depending on the particular dates and time zone.
Duration.between(
ZonedDateTime.of( 2019 , 1 , 23 , 23 , 0 , 0 , 0 , ZoneId.of( "Africa/Cairo" ) ) ,
ZonedDateTime.of( 2019 , 1 , 24 , 7 , 30 , 0 , 0 , ZoneId.of( "Africa/Cairo" ) )
)
.toString()
See this code run live at IdeOne.com.
PT8H30M
Calculating elapsed time requires date, time-of-day, and time zone
The Answer by Markus Hänsel is headed the right way, but fails to account for anomalies such as Daylight Saving Time (DST).
Your Question is not quite clear. Do you mean to track the general idea of time-of-day using generic 24-hour days? Or do you mean to track actual moments, such as the time slept two days ago, the time slept yesterday, and so on?
If the latter, then you cannot use LocalDateDate as that class cannot, by definition, track moments. The LocalDateTime class lacks any concept of time zone or offset-from-UTC. As such, a LocalDateTime represents potential moments along a range of about 26-27 hours (the range of time zones around the globe).
Given your example of 11:00 pm to 7:30 am, that would mean 8.5 hours in a certain time zone with no anomalies on that date. But on a day of DST cut-over that might mean 7.5 hours (“Spring ahead”), or 9.5 hours (“Fall back”). Or maybe 8.0 hours on day such as last year when North Korea adjusted their clock by a half-hour. Or when in 2007 Venezuela turned back time a half-hour… and then a decade later flipped back again. These changes happen more often than you may realize. Politicians around the globe have shown a penchant for redefining the offset of their time zone(s).
➥ The upshot is that you cannot reliably calculate elapsed time with only the time-of-day. You must use a date and a time zone.
ZoneId
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime
To track moments, use the ZonedDateTime class. This class combines a date, a time-of-day, and a time zone.
LocalDate ldStart = LocalDate.of( 2019 , 1 , 23 ) ;
LocalTime ldStart = LocalTime.of( 23 , 0 ) ;
ZonedDateTime zdtStart = ZonedDateTime.of( ldStart , ltStart , z ) ;
And the stop time.
LocalDate ldStop = LocalDate.of( 2019 , 1 , 24 ) ; // Next day.
LocalTime ldStop = LocalTime.of( 7 , 30 ) ;
ZonedDateTime zdtStop = ZonedDateTime.of( ldStop , ltStop , z ) ;
Calculate elapsed time using Duration class.
Duration d = Duration.between( zdtStart , zdtStop ) ;
ISO 8601
I recommend you not report elapsed time using time-of-day format, HH:MM:SS. Instead use the standard format defined for this purpose, in the ISO 8601 standard.
So, 8.5 hours would be PT8H30M.
The java.time classes use ISO 8601 formats by default when parsing/generating strings.
String output = d.toString() ; // Generate `PT8H30M`.
And parsing.
Duration d = Duration.parse( "PT8H30M" ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
You can use the SimpleDateFormat for getting the input. I'm using the predefined input, since you wanted the difference calculation between two given times. Here is the code fo you. Please note I have given out the answer for both 24 or 12 hours format.
Getting the value of sleep time and waking up time
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
Date sleepingTime = simpleDateFormat.parse("22:00");
Date wakeUptime = simpleDateFormat.parse("07:00");
For difference is less than zero, this happens in 12 hours format
long difference = sleepingTime.getTime() - wakeUpTime.getTime();
if(difference<0) {
Date dateMax = simpleDateFormat.parse("24:00");
Date dateMin = simpleDateFormat.parse("00:00");
difference=(dateMax.getTime() -sleepingTime.getTime() )+(wakeUpTime.getTime()-
dateMin.getTime());
}
Calculating the difference
//days and minutes are optional
int days = (int) (difference / (1000*60*60*24));
int hours = (int) ((difference - (1000*60*60*24*days)) / (1000*60*60));
int min = (int) (difference - (1000*60*60*24*days) - (1000*60*60*hours)) /
(1000*60);
Log.e("log_tag",hours+" hours");
I hope it will answer your query. Thanks :)
Just Try following line of code to get difference in minutes
import java.util.concurrent.TimeUnit; // predefined method from java 6.
private long subtractTwoDates(Date date1, Date date2) {
Long diffInMinutes=null,diff=null; // just declaration of variables
diff = date1.getTime() - date2.getTime();
diffInMinutes= TimeUnit.MILLISECONDS.toMinutes(diff);
log.info("diff min : "+difInMin);
return diffInMinutes; // returns long value in minutes.
}
Related
I was looking to do a simple script of setting a time every 10minutes on Oct 26th 2020.
My loop looks like below.
However even though the time generally seems right when i output 'time' var, then i convert it to Date object and do a toString() on that 'd' variable then it seems to convert it to another time. If you want to see it run on an online java compiler you can see it in action here:
https://ideone.com/T8anod
You can see it do strange stuff like:
0:00 AM
Mon Oct 26 10:00:00 GMT 2020
0:10 AM
Mon Oct 26 10:10:00 GMT 2020
...
12:00 PM
Mon Oct 26 22:00:00 GMT 2020
12:10 PM
...
Mon Oct 26 22:10:00 GMT 2020
One unusually thing is i'll set a breakpoint in my IDE at 12 hours... and if I debug slowly it will set the correct time. Then i'll remove my breakpoint and play through the rest of the script and the times then end up incorrect again. Very unusual behavior I haven't seen in Java yet.
I could do something like this to reset the hours (or use a different technique):
Date d = cal.getTime();
d.setHours(hour); //deprecated
But I'd rather just figure out for now why Java is acting this way.
for(int hour=0; hour < 24; hour++ ) {
for(int minute = 0; minute < 6; minute++) {
String str_min = minute==0 ? "00" : String.valueOf(minute*10);
String time = String.valueOf( hour > 12 ? hour-12 : hour) +":"+ str_min +" "+ ((hour >= 12 ? Calendar.PM : Calendar.AM)==1 ? "PM" : "AM");
//note: got lazy and not outputting "00" for hour
System.out.println( time );
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, 9); //Oct=9
cal.set(Calendar.DAY_OF_MONTH, 26);
cal.set(Calendar.YEAR, 2020);
cal.set(Calendar.HOUR_OF_DAY, hour );
cal.set(Calendar.MINUTE, minute*10 ); //0=0, 1=10, ... 5=50
cal.set(Calendar.AM_PM, (hour >= 12 ? Calendar.PM : Calendar.AM) );
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date d = cal.getTime();
System.out.println( d.toString() );
}
}
java.util.Date is a lie. It does not represent a date; it represents an instant in time, it has no idea about timezones, or this concept of 'hours'. That's why everything (except the epoch-millis-based methods and constructors) are marked deprecated.
The calendar API tries to fix this, but is a horrible, horrible API.
Use java.time instead. The ugly API goes away, and unlike the old stuff, you have types that actually represent exactly what you want. Given that you aren't messing with timezones here, you want LocalDateTime:
for (int hour = 0; hour < 24; hour++) {
for (int minute = 0; minute < 60; minute += 10) {
LocalDateTime ldt = LocalDateTime.of(2020, 10, 26, hour, minute, 0);
System.out.println(ldt);
// or better:
System.out.println(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(ldt));
}
}
Note how October is '10' in this API, because this API is not insane, for example. You can use any of the many predefined formatters in DTF, or write your own with a pattern to control precisely how you want to render the date.
If you want to represent other things, you can do so; ZonedDateTime for a specific time the way humans would say it (say: I have an appointment with the dentist, who is in Rome, at a quarter past 2 in the afternoon on november 2nd, 2020). The point of such a concept is this: If Rome decides to switch timezones, then the actual instant in time your appointment occurs should change along with it.
If you want an instant in time, there's Instant. This is a specific moment in time (in the past or future) that will not change in terms of how many milliseconds remain until it occurs. Even in the face of countries changing their zone.
And LDT is, well, LDT: It just represents a year, a month, a day, hours, minutes, and seconds - without a timezone.
tl;dr
LocalDate
.now( ZoneId.of( "America/Chicago" ) ) // Today
.atStartOfDay( ZoneId.of( "America/Chicago" ) ) // First moment of today. Returns a `ZonedDateTime` object.
.plus(
Duration.ofMinutes( 10 ) // Ten minutes later.
) // Returns another `ZonedDateTime` object.
Avoid legacy date-time classes
You are using terrible date-time classes that were supplanted years ago by the java.time classes. Sun, Oracle, and the JCP gave up on those classes, and so should you.
Rather than try to understand those awful classes, I suggest you invest your effort in learning java.time.
Use java.time
Much easier to capture a Instant object when you want the current date-time moment.
Note that java.time uses immutable objects. Rather than alter an existing object, we generate a fresh one.
To represent a moment for every ten-minute interval of today:
ZoneId z = ZoneId.of( "Africa/Tunis" ) ; // Or "America/New_York", etc.
LocalDate today = LocalDate.now( z ) ;
Your code makes incorrect assumptions. Days or not always 24 hours long. They may be 23 hours, 25 hours, or some other length. Also not every day in every time zone starts at 00:00. Let java.time determine the first moment of the day.
ZonedDateTime start = today.atStartOfDay( z ) ;
Get the start of the next day.
ZonedDateTime stop = start.plusDays( 1 ) ;
Loop for your 10-minute chunk of time. Represent that chunk as a Duration.
Duration d = Duration.ofMinutes( 10 ) ;
List< ZonedDateTime > results = new ArrayList<>() ;
ZonedDateTime zdt = start ;
while( zdt.isBefore( stop ) )
{
results.add( zdt ) ;
zdt = zdt.plus( d ) ;
}
See this code run live at IdeOne.com.
Strings
You can generate strings in any format to represent the content of those ZonedDateTime objects. You can even let java.time automatically localize.
Locale locale = Locale.CANADA_FRENCH ; // Or Locale.US etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale ) ;
String output = myZonedDateTime.format( f ) ;
In particular, Locale.US and FormatStyle.MEDIUM might work for you. Fork the code at IdeOne.com to experiment.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 brought some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android (26+) bundle implementations of the java.time classes.
For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….
The other answers tell you to use a different API, i.e. to not use Calendar, and they are right, but they don't tell you why the question code doesn't work.
If you read the documentation of Calendar, and look for section "Calendar Fields Resolution", you will find (bold highlight by me):
Calendar Fields Resolution
When computing a date and time from the calendar fields, there may be insufficient information for the computation (such as only year and month with no day of month), or there may be inconsistent information (such as Tuesday, July 15, 1996 (Gregorian) -- July 15, 1996 is actually a Monday). Calendar will resolve calendar field values to determine the date and time in the following way.
If there is any conflict in calendar field values, Calendar gives priorities to calendar fields that have been set more recently. The following are the default combinations of the calendar fields. The most recent combination, as determined by the most recently set single field, will be used.
For the date fields:
YEAR + MONTH + DAY_OF_MONTH
YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
YEAR + DAY_OF_YEAR
YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
For the time of day fields:
HOUR_OF_DAY
AM_PM + HOUR
The question code has:
cal.set(Calendar.HOUR_OF_DAY, hour );
cal.set(Calendar.AM_PM, (hour >= 12 ? Calendar.PM : Calendar.AM) );
Since the last of those fields set is AM_PM, it resolved the hour using AM_PM + HOUR, and since you never call clear() and never set HOUR, the value is the 12-hour clock value set by the getInstance() call, i.e. the current time.
You have 2 choices to fix this:
// Only set the 24-hour value
cal.set(Calendar.HOUR_OF_DAY, hour);
// Set the 12-hour value
cal.set(Calendar.HOUR, hour % 12);
cal.set(Calendar.AM_PM, (hour >= 12 ? Calendar.PM : Calendar.AM) );
I would recommend doing the first one.
I would also highly recommend calling clear() before setting fields, so the result is not polluted by left-over values. That would eliminate the need to set SECOND and MILLISECOND to 0.
Actually, I would recommend using the newer Time API, like the other answers do, but at least you now know why the code was failing.
I want to the milliseconds to the next hours. For example
Now time -> 10:01:23 2nd Oct, 2018, Want remaining milliseconds to 11:00:00 2nd Oct, 2018.
The Now time is dynamic, it can be 23:56:56 2nd Oct, 2018 and next hour is at 00:00:00 3rd Oct, 2018.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(startDate.getMillis());
calendar.add(Calendar.HOUR, 1);
I was trying something like this, but it is adding 1 hour to the startDate. But I want exact next hour.
Any help is welcomed.
Since Java8, you can use java.time.LocalDateTime:
LocalDateTime start = LocalDateTime.now();
// Hour + 1, set Minute and Second to 00
LocalDateTime end = start.plusHours(1).truncatedTo(ChronoUnit.HOURS);
// Get Duration
Duration duration = Duration.between(start, end);
long millis = duration.toMillis();
Running just now (2018-10-02T18:44:48.943070 Peking time) I got 911 056 milliseconds.
A simple arithmetic approach:
long hourInMillis = 60 * 60 * 1000;
long startDateInMillis = startDate.getMillis();
long millisSinceLastHourChange = startDateInMillis % hourInMillis;
long millisToNextHourChange = hourInMillis - millisSinceLastHourChange;
works since Java 1 ;-)
EDIT
This approach doesn't take DST or similar changes into account.
tl;dr
Hours on the clock are not always an hour long.
Leverage a time zone to handle such cases.
Duration
.between(
zonedDateTime_Now ,
zonedDateTime_FirstMomentOfHourLater
)
.toMillis()
Beware of anomalies
If you want to account for real-world anomalies in wall-clock time used by your intended time zone, you must specify a time zone. This means using the ZonedDateTime class.
An hour is not always an hour. For example, North Korea recently adjusted its offset-from-UTC by half-an-hour. This means one hour will last only 30 minutes during the adjustment jump. This example of North Korea is only one of the most recent examples. Politicians around the world show a surprising penchant for redefining their time zone(s).
Time zone
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
Add an hour.
ZonedDateTime hourLater = now.plusHours( 1 ) ;
Truncate to the hour.
ZonedDateTime firstMomentOfNextHour = hourLate.truncatedTo( ChronoUnit.HOURS ) ;
Elapsed time
Calculate elapsed time as a Duration object.
Duration d = Duration.between( now , firstMomentOfNextHour ) ;
The java.time classes use nanosecond resolution, but you asked for milliseconds. So understand that there is data-loss involved in reporting milliseconds.
long milliseconds = d.toMillis() ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
A java.time solution using ZonedDateTime.until:
ZonedDateTime startDate = ZonedDateTime.now();
LocalDateTime nextHour = startDate.plusHours(1).truncatedTo(ChronoUnit.HOURS);
long msUntillNextHour = startDate.until(nextHour, ChronoUnit.MILLIS);
I searched for this is SO there are so many post asking this question but all the answers is difference In Milliseconds / (24* 1000 * 60 * 60) that gives the number of 24 Hrs between two dates .
but i need the number of days between 2 dates.
I.e. if date1 is 09/09/13 09:00 and date2 is 10/09/13 22:00 I need the difference as 0 and not 1 because date1 and date2 are consecutive days (even if there is more than 24 hour gap between them).
Note: I know the removing the time part and using the difference In Milliseconds / (24* 1000 * 60 * 60) method. I am looking for a better solution.
update: the app is first used on 09/09/13 09:00 its a Wednesday then the app was used on 10/09/13 22:00` its Thursday. now the user has used the app both Wednesday and Thursday even though there is more than 24 hour gap. now if i calculate the number of 24 hours between the 2 dates it gives one. as there is a day gap between 2 dates. i need it to give zero as the user used it Wednesday and Thursday there is NO DAY BETWEEN WEDNESDAY AND THURSDAY.
hope you understood my question. if you still didn't just leave it, i tried by best explaining.
Here's a simple solution:
Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);
while(calendar.getTime().before(endDate))
{
noOfDays++;
calendar.add(Calendar.DAY_OF_MONTH,1);
}
Where startDate and endDate are instances of the Date class.
Note: You need to initialize the date objects so that they have the same time but only differ in their dates. Setting them both to 12 AM should do the trick:
date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.text.SimpleDateFormat;
import java.text.ParseException;
public class test {
public static void main(String[] args) throws ParseException {
String dateStart = "09/09/13 09:00";
String dateStop = "10/09/13 22:00";
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");
Date date1 = format.parse(dateStart);
Date date2 = format.parse(dateStop);
// calculate difference in milliseconds
long diff = (date2.getTime() - date1.getTime()) - 86400000;
diff = (diff <= 0 ? 0 : diff);
System.out.println(TimeUnit.MILLISECONDS.toDays(diff));
}
}
This will give the difference between 2 dates. And subtract a day (if its negative, it sets the difference to 0 day). This will work as long as dateStop is greater than dateStart, otherwise it will just print 0;
I have avoided using Joda Time for ages, but this past week I got round to using it for exactly this issue. And it was well worth it!
It is very easy to introduce some strange date handling bugs when dealing with plain Java - for example what happens when daylight savings time changes. Joda Time builds all these exceptions in already.
Check related question here:
Number of days between two dates in Joda-Time
Update
As of Java 8, the time & date functionality has been improved, and the Joda Time team suggests using that instead of their library. Here's what they say on the landing page:
Note that from Java SE 8 onwards, users are asked to migrate to
java.time (JSR-310) - a core part of the JDK which replaces this
project.
Thanks to Basil Bourque for the comment.
You can use this trick: if date1 is before date2 you can set hour in date1 to 1 and in date2 to 0. This way hour part in entire time difference will never be greater than 24h, so will not affect calculations so only days/months/years will matter.
Here is code example
public static long daysBetween(Date date1, Date date2) {
Calendar c1 = Calendar.getInstance();
c1.setTime(date1);
Calendar c2 = Calendar.getInstance();
c2.setTime(date2);
if (date1.before(date2)) {
c1.set(Calendar.HOUR_OF_DAY, 1);
c2.set(Calendar.HOUR_OF_DAY, 0);
} else {
c2.set(Calendar.HOUR_OF_DAY, 1);
c1.set(Calendar.HOUR_OF_DAY, 0);
}
return (c2.getTimeInMillis() - c1.getTimeInMillis())
/ (24 * 60 * 60 * 1000);
}
//DEMO
public static void main(String[] args) throws Exception {
DateFormat df = new SimpleDateFormat("dd/MM/yy hh:mm");
Date date1 = df.parse("09/09/13 09:00");
Date date2 = df.parse("11/09/13 22:00");
System.out.println(daysBetween(date1, date2));
}
Output: 1
For dates 11/09/13 09:00 09/09/13 22:00 result will be -1 since date1 is after date2
tl;dr
ChronoUnit.DAYS.between(
earlierInstant.atZone( ZoneId.of( "Africa/Tunis" ) ).toLocalDate() ,
Instant.now().atZone( ZoneId.of( "Africa/Tunis" ) ).toLocalDate()
)
java.time
The modern approach uses the java.time classes that supplanted the troublesome old date-time classes such as Date & Calendar.
If you want to calculate the number of elapsed days as the number of calendar dates rather than the number of 24-hour chunks of time, use a date-only class rather than a date-time class.
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
Generally best to think, work, log, serialize, and exchange values in UTC. For that, use Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant earlier = Instant.now() ;
…
Instant later = Instant.now() ;
Serialize to text in standard ISO 8601 format by calling Instant::toString and Instant::parse.
To get your elapsed dates, apply a time zone (ZoneId) to get ZonedDateTime objects.
ZonedDateTime zdtEarlier = earlier.atZone( z ) ;
ZonedDateTime zdtLater = later.atZone( z ) ;
Extract the date-only values.
LocalDate ldEarlier = zdtEarlier.toLocalDate() ;
LocalDate ldLater = zdtLater.toLocalDate() ;
Now we can get the elapsed days between the dates.
long daysElapsed = ChronoUnit.DAYS.between( ldEarlier , ldLater ) ;
This calculation is done per the Half-Open approach where the beginning is inclusive while the ending is exclusive. So, for example, a month starts with the first day of the month and runs up to, but does not include, the first day of the following month. Using this approach consistently throughout your business logic, database queries, and so on will make your codebase less error-prone and easier to read/debug/maintain.
I understand you want to use a fully-Open approach where both beginning and ending is exclusive. I strongly suggest you reconsider that position. But if you insist, simply subtract 1 from our calculation above.
long daysElapsedFullyOpen = ( ChronoUnit.DAYS.between( ldEarlier , ldLater ) - 1 ) ; // Subtract 1 to get a fully-Open answer. NOT recommended.
By the way, you may want to consider the Period class in your work. Similarly, you may find useful the LocalDateRange class found in the ThreeTen-Extra project.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I am using the compareTo method in Java to try and check if a certain date is greater than or equal than 24 hours after another date.
How do I determine what integer to compare the date to?
Use the Calendar class. If you already have a Date object, you can still use Calendar:
Date aDate = . . .
Calendar today = Calendar.getInstance();
today.setTime(aDate);
Calendar tomorrow = Calendar.getInstance();
tomorrow.setTime(aDate);
tomorrow.add(Calendar.DAY, 1);
Date tomorrowDate = tomorrow.getTime(); // if you need a Date object
Answer depends on what you want to achieve.
One way, could be checking difference in milliseconds. 24 h in milliseconds can be calculated via
24 * 60 * 60 * 1000 = 86400000
h min sec millis
(in code you can also write TimeUnit.HOURS.toMillis(24) which IMO is more readable)
So now you can just check if difference between two dates (expressed in milliseconds) is greater than 86400000.
tl;dr
myUtilDate_B
.toInstant()
.equals(
myUtilDate_A.toInstant().plus( 24 , ChronoUnit.HOURS )
) // Exactly 24 hours apart.
…and…
myUtilDate_B
.toInstant()
.isAfter(
myUtilDate_A.toInstant().plus( 24 , ChronoUnit.HOURS )
) // Over 24 hours apart.
Alternatively…
Duration.between( myUtilDate_A , myUtilDate_B )
.compareTo( Duration.ofHours( 24 ) )
// Returns 0 if exactly 24 hours apart,
// >0 if over 24 hours apart.
java.time
You specifically asked for comparing two date-times to ask if either:
Is one exactly 24 hours later than another
Is one more than 24 hours later than another.
The compareTo method you mentioned does not do this. It is designed to merely tell if a moment is the same, later, or sooner. The method does not care about specific spans of time such as 24 hours.
You specifically stated that the date does not matter. So you want to ignore anomalies such as Daylight Saving Time (DST) that make a day longer or shorter than 24 hours.
So we can work in UTC. No need for time zones.
If you were referring to java.util.Date objects, first convert them to java.time objects. The Date class is part of the troublesome old date-time classes, along with Calendar, that are now legacy, supplanted by the java.time classes.
The equivalent of java.util.Date is java.time.Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
You can convert to/from java.time types via new methods added to the old classes.
Instant start = myUtilDate_Start.toInstant();
Instant stop = myUtilDate_Stop.toInstant();
Define the gap we care about, in this case twenty four hours, as a Duration object.
Duration d = Duration.ofHours( 24 ); // We mean literally 24 hours, not a day.
Use that Duration to calculate the 24-hours-later value. Define the unit of hours by the ChronoUnit enum.
Instant target = start.plus( 24 , ChronoUnit.HOURS );
Lastly, compare the second date-time value. Call equals and isAfter.
Boolean isExactly24HoursLater = stop.equals( target );
Boolean isOver24HoursLater = stop.isAfter( target );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Joda-Time
UPDATE: The Joda-Time project, now in maintenance mode, advises migration to the java.time classes. This section is left here intact for history.
Joda-Time makes this work easier.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime dateTimeInQuestion = new DateTime( 2014, 1, 2, 3, 4, 5, 6, timeZone ); // Or: new DateTime( someJavaDotUtilDotDateObject );
DateTime now = new DateTime( timeZone );
DateTime twentyFourHoursFromNow = now.plusHours( 24 ); // Ignores Daylight Saving Time (DST). If you want to adjust for that, call: plusDays( 1 ) instead.
DateTime isDateTimeInQuestionAfter24HoursFromNow = dateTime.isAfter( twentyFourHoursFromNow );
1 Day ≠ 24 Hours
If you really meant to consider the same wall-clock time of the next day, call plusDays( 1 ) rather than plusHours( 24 ). Joda-Time then adjusts for Daylight Saving Time (DST) or other anomalies. For example, here in the United States, that might mean 25-hours rather than 24-hours because of our 1-hour DST silliness.
Compare Within 24-Hours
If really meant to test if the date-time in question lands within that 24-hour span of time, use one of Joda-Time's three classes for spans of time: Interval, Duration, and Period.
Interval interval = new Interval( now, twentyFourHoursFromNow );
boolean isDateTimeInQuestionContainedWithinNext24Hours = interval.contains( dateTimeInQuestion );
For that kind of comparison, Joda-Time uses "Half-Open" logic. This means the beginning date-time is inclusive while the ending is exclusive. In other words, comparing for GREATER THAN OR EQUAL TO (>=) the start, but LESS THAN (<) the ending. This approach usually makes the most sense when working with date-time.
This will help you check if your date was yesterday
public static final long ONE_MINUTE = 60 * 1000;
public static final long ONE_HOUR = 60 * ONE_MINUTE;
public static final long ONE_DAY = 24 * ONE_HOUR;
public static boolean isYesterday(Date d) {
return DateUtils.isToday(d.getTime() + ONE_DAY);
}
In your Activity OnCreate
//Get current date - yymmdd increases only
SimpleDateFormat formatter = new SimpleDateFormat("yyMMdd");
Date now = new Date();
int nowTime= Integer.parseInt(formatter.format(now));
//Get last login date - stored in db
int lastLogin= dbManager.getLastLoginDate();
//Check if next day
if(nowTime> lastLogin){
//Do your stuff
//Update last login date
dbManager.saveLoginDate(nowTime);
}
To find the delta between dates: In short,
long endL = end.getTimeInMillis() + end.getTimeZone().getOffset( end.getTimeInMillis() );
long startL = this.getTimeInMillis() + this.getTimeZone().getOffset(this.getTimeInMillis());
return (endL - startL) / MILLISECS_PER_DAY;
In detail,
http://user.xmission.com/~goodhill/dates/deltaDates.html
Is it possible to subtract time from a calendar?
e.g.
.....
Calendar DueTime = Calendar.getInstance();
Calendar ReminderTime = Calendar.getInstance();
int ReminderMinute = 5;
DueTime.set(DueYear, DueMonth, DueDay, DueHour, DueMinute);
Day = Day - reminderDays ;
Day = Day - (Week*7) ;
Month = Month - reminderMonths ;
Year = Year - reminderYears ;
Hour = Hour - reminderHours ;
Minute= Minute- reminderMinutes;
ReminderTime.set(Year, Month, Day, Hour, Minute );
ReminderTime.add(Calendar.DAY_OF_MONTH , - Day );
ReminderTime.add(Calendar.MONTH , - Month );
ReminderTime.add(Calendar.YEAR , - Year );
ReminderTime.add(Calendar.HOUR , - Hour );
ReminderTime.add(Calendar.MINUTE , - Minute);
If the above is possible another question I would like to know is if...
reminderDays = 60;
Then would that go into the month before it as well?
Say its the 31st of the month that the due date is and the month before it has 30 days would the reminder day be the 1st of that month?
On another note that's related:
I'm not sure if I am right or not but does a calendar instance store time in milliseconds?
e.g. 1 minute would be 600 milliseconds and an hour would be 36000 milliseconds
So if I did:
ReminderTime.add(Calendar.HOUR , - 1 );
all it would be doing is adding -36000 to the total time stored in that calendar object
so if that's true would doing:
ReminderTime.add(Calendar.DAY_OF_MONTH , - 60 );
result in it subtracting 51840000 milliseconds? Or would I need to change
ReminderTime.add(Calendar.DAY_OF_MONTH , - 60 );
to
ReminderTime.add(Calendar.DAY_OF_YEAR , - 60 );
This would be after I call:
ReminderTime.set(Year, Month, Day, Hour, Minute );
What I expect from this above is that my activity will calculate which day of the year that calendar object is and remove 51840000 milliseconds from it.
Can anyone help?
Three different questions here, separated by lines
Three questions, two statements which should enable you to answer them yourself.
1) Yes you can subtract by adding a negative number as you have written.
2) The fields carry, just like units,tens,hundreds do. So taking 60 off the DAY_OF_MONTH will carry into the previous month or months or year if necessary. It will adjust the calendar by 60 days
P.S. 1 minute isn't 60 milliseconds! It's 60 x 1000 = 60,000 milliseconds
tl;dr
ZonedDateTime.now()
.minusMonths( 2 )
…versus…
ZonedDateTime.now()
.minusDays( 60 )
Avoid legacy date-time classes
The troublesome old date-time classes are now legacy, supplanted by the java.time classes.
java.time
Yes, you can easily do math with dates in java.time. The various classes include plus… and minus… methods.
Get current moment, as a ZonedDateTime.
ZonedDateTime now = ZonedDateTime.now() ;
Better to specify the desired/expected time zone than rely implicitly on the JVM’s current default.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
Subtract an hour.
ZonedDateTime zdt = now.minusHour( 1 ) ;
Note that anomalies such as Daylight Saving Time (DST() cut-over are handled for you automatically.
If you want to subtract exactly 60 days…
ZonedDateTime zdt = now.minusDays( 60 ) ;
But if you meant two months, that would be different logic. Read the documentation for exact behavior.
ZonedDateTime zdt = now.minusMonths( 2 ) ;
You can also use the Period class for a span of time in granularity of days-month-years. These are generic months or calendar-based days, not 24-hour days.
Period twoMonths = Period.ofMonths( 2 ) ;
ZonedDateTime zdt = now.minus( twoMonths ) ;
If you meant to represent sixty generic (24-hours) days as a number of nanoseconds, use Duration.
Duration d = Duration.ofDays( 60 ) ;
ZonedDateTime zdt = now.minus( d ) ;
Tip: If you only need the date portion, and not the time-of-day, use LocalDate class.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….