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….
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 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.
}
I am trying to calculate an offset time from a given date. I get the date as a String and parse it, and I have the offset in milliseconds. So for example
Date: 2015-08-18 00:00:00
Offset Time: 2678400000, which when applied to the date, it equals 2015-09-18 00:00:00, 31 days later.
My goal is to store each of the offsets (years/months/days/hours/minutes/seconds) in an array, so I can use it later.
However when I run this calculation using the Calendar class, I'm getting extra hours for some reason when called with offsetConverter(2678400000)
Output: 0 years 0 months 31 days 19 hours 0 minutes 0 seconds
Here is my code which I found and modified slightly from this link Best way to convert Milliseconds to number of years, months and days
public static int[] offsetConverter(long offset) {
int[] delay = new int[6];
//delay 0-3 = years/months/days/seconds
Calendar c = Calendar.getInstance();
c.setTimeInMillis(offset);
delay[0] = c.get(Calendar.YEAR) - 1970;
delay[1] = c.get(Calendar.MONTH);
delay[2] = c.get(Calendar.DAY_OF_MONTH);
delay[3] = c.get(Calendar.HOUR_OF_DAY);
delay[4] = c.get(Calendar.MINUTE);
delay[5] = c.get(Calendar.SECOND);
for (int i = 0; i< delay.length; i++)
System.out.print(delay[i] + " ");
System.out.println();
return delay;
}
If anyone sees what I'm doing wrong or has a simpler way to do this I would appreciate the help. Thanks!
Milliseconds from Date#getTime() arrive in UTC timezone, but you instantiate calendar with default timezone, which is your local. This adds extra hours to your result.
To solve this issue, create a Calendar instance using UTC timezone:
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
tl;dr
LocalDateTime.parse(
"2015-08-18 00:00:00".replace( " " , "T" ) // Convert input string to comply with ISO 8601 standard format, replacing SPACE in the middle with a `T`.
).plus(
Duration.ofDays( 31 ) // If you meant ( 31 * 24-hours ).
// Period.ofDays( 31 ) // If you meant 31 calendar-days.
// Period.ofMonths( 1 ) // If you meant a calendar-month.
) // Returns a fresh `LocalDateTime` object, distinct from original, per Immutable Objects pattern.
.toString() // Generate a string in standard ISO 8601 format to textually represent this object’s value.
2015-09-18T00:00
Terms
The word “offset” here is a poor choice of terms. That word has a specific meaning in date-time handling: the amount of hours, minutes, and seconds a time zone is from UTC. See the Wikipedia entry for UTC offset.
You seem to be concerned instead with a span of time unattached to the timeline. In the java.time classes such spans are called a Duration if in the scale of hours-minutes-seconds, and called Period if scaled in years-months-days.
java.time
The modern approach uses the java.time classes that supplanted the troublesome old date-time classes such as Date/Calendar.
Duration
Convert your span of time from a count of milliseconds to a Duration object.
Duration d = Duration.ofMillis( 2_678_400_000L );
This happens to be 744 hours.
d.toString(): PT744H
Out of curiosity, I checked the number of days in 744 hours, if we define “days” to be chunks of 24-hours.
d.toDaysPart(): 31
So it seems you really intend a month or a period of 31 days. Either way, Java has classes for that.
If you really want: ( 31 * 24 hours ), then do use a Duration. But construct the Duration object with more self-documenting code.
Duration d = Duration.ofDays( 31 ) ; // Exact same effect as `Duration.ofMillis( 2_678_400_000L )` but more clear as to your intention.
ISO 8601
Your input string almost complies with ISO 8601 standard for date-time formats. The java.time classes use the standard formats by default when parsing/generating strings.
Convert your string to comply. Replace the SPACE in the middle with a T.
String input = "2015-08-18 00:00:00".replace( " " , "T" ) ;
2015-08-18T00:00:00
LocalDateTime
Parse your input as a LocalDateTime as your input lacks an indicator of offset-from-UTC or time zone.
LocalDateTime ldt = LocalDateTime.parse( input ) ;
ldt.toString(): 2015-08-18T00:00
Add your Duration object to get a new fresh LocalDateTime. The java.time classes use immutable objects so the original object is left intact.
LocalDateTime thirtyOneTimes24HoursLaterLdt = ldt.plus( d ) ; // Adding a span-of-time to our `LocalDateTime` object to get another `LocalDateTime` object.
thirtyOneTimes24HoursLaterLdt.toString(): 2015-09-18T00:00
Be aware that LocalDateTime does not represent an actual moment, a specific point on the timeline. Without the context of a time zone or offset-from-UTC, it is only a rough idea about potential moments along a range of about 26-27 hours.
ZonedDateTime
If you know for certain your input string was meant to represent a moment in a particular zone, apply a ZoneId to get a ZonedDateTime object (an actual moment).
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ; // Now we have determined an actual moment, a point on the timeline.
zdt.toString(): 2015-08-18T00:00+12:00[Pacific/Auckland]
You can add your Duration if you do not care about dates (whole days on the calendar).
ZonedDateTime thirtyOneTimes24HoursLaterZdt = zdt.plus( d ) ;
thirtyOneTimes24HoursLaterZdt.toString(): 2015-09-18T00:00+12:00[Pacific/Auckland]
If your business logic was really meant to be thirty-one days on the calendar, use a Period.
ZonedDateTime thirtyOneDaysLater = zdt.plus( Period.ofDays( 31 ) ) ;
thirtyOneDaysLater.toString(): 2015-09-18T00:00+12:00[Pacific/Auckland]
If your business logic is really intending a calendar month rather than a specific number of days, use a different Period. The class makes adjustments as needed to handle various months’ length (read the doc and follow that doc’s link).
ZonedDateTime monthLater = zdt.plus( Period.ofMonths( 1 ) ) ;
monthLater.toString(): 2015-09-18T00:00+12:00[Pacific/Auckland]
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.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor 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, 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 wrote simple java program in which I get day of month, days in month and month
see below code :
//Calendar calendar = Calendar.getInstance();
Calendar calendar = new GregorianCalendar();
log.info("day of month: "+calendar.get(Calendar.DAY_OF_MONTH));
calendar.set(Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH);
log.info("days in month: "+calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
log.info("month: "+calendar.get(Calendar.MONTH));
Running above code I get this output:
day of month: 7
days in month: 31
month: 2
But when I put below statement
log.info("month: "+calendar.get(Calendar.MONTH));
before
log.info("day of month: "+calendar.get(Calendar.DAY_OF_MONTH));
I get this output: (which is what I want)
day of month: 7
days in month: 31
month: 5
Can any body help me understand why I get month: 2 ?
Youre setting the Calendar field to Calendar.MONTH (value 2) here
calendar.set(Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH);
^
You can do this
calendar.set(2014, Calendar.JUNE, 1);
although the Month 5 is June (since month field starts from 0 for Calendar) which only has 30 days
Look at the source code of Calendar.java of JDK.
public final static int MONTH = 2;
Here, Calendar.MONTH = 2, Calendar.YEAR=1 and Calendar.DAY_OF_MONTH = 5. You set these constant value to calender using set method like.
calendar.set(Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH);
| | |
1 2 5
tl;dr
LocalDate.now()
.getDayOfMonth()
…and…
YearMonth.from(
LocalDate.now()
).lengthOfMonth() // .getMonthValue() .getYear()
java.time
The modern approach uses the industry-leading java.time classes.
LocalDate
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" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Parts
Interrogate for the parts as needed.
int dayOfMonth = ld.getDayOfMonth() ;
int month = ld.getMonthValue() ;
int year = ld.getYear() ;
YearMonth
To work with the month as a whole, use YearMonth class.
YearMonth ym = YearMonth.from( ld ) ;
Ask for length of month.
int lengthOfMonth = ym.lengthOfMonth() ;
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
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, 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