I am trying to create a method in Java that returns true if the current time of day is between a set interval (startTime and endTime).
The date is irrelevant. What is the best way to do this?
Here is my attempt it doesn't work:
public boolean isNowBetweenDateTime()
{
final Date now = new Date();
return now.after(startTime) && now.before(endTime);
}
What is the best way (in java) to check if time is within two Date objects, ignoring year, month day?
Your code looks good. Just set the date of now, startTime and endTime to some hard coded value.
tl;dr
Interval.of( start.toInstant() , stop.toInstant() ).contains( Instant.now() )
Half-Open
In date-time handling, the Half-Open approach is commonly used for defining a span of time. The beginning is inclusive while the ending is exclusive. So a week is defined as starting at the first moment of a Monday and running up to, but not including, the first moment of the following Monday. We sometimes use this Half-Open approach intuitively, where a lunch period of 12 to 1 means start at the stroke of noon but be back at your job or class before the clock strikes 1 PM. Using Half-Open consistently throughout your date-time work will make the logic and programming cleaner, clearer, and simpler.
So your logic should be, “Is now not before beginning AND now is before ending”. Notice that “not before” is a compact way of saying “is equal to OR is after”.
boolean isNowBetweenDateTime = ( ! now.before(startTime) ) && now.before(endTime) ; // Not before start AND is before stop.
ZonedDateTime
The Question and other Answers use troublesome old legacy date-time classes now supplanted by the java.time classes.
The ZonedDateTime class represents a moment on the timeline with an assigned time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( z );
ZonedDateTime start = now.minusWeeks( 1 ); // Simulating input.
ZonedDateTime stop = now.plusWeeks( 2 ); // Simulating input.
You could write the logic yourself to test if now is between.
Boolean isBetween = ( ! now.isBefore( start ) ) && stop.isBefore( stop );
Interval
If doing more of this kind of work, look at the ThreeTen-Extra project. This library extends the java.time classes with additional functionality. Specifically the Interval class will be helpful, representing a pair of moments on the timeline. Implements a variety of comparison methods such as contains, encloses, abuts, and overlaps.
Instantiate a Interval with a pair of Instant objects. Instant represents a moment on the timeline in UTC. We can extract an Instant object from each ZonedDateTime object.
Interval interval = Interval.of( start.toInstant() , stop.toInstant() );
Boolean isBetween = interval.contains( now.toInstant() ); // Or pass `Instant.now()`.
You can also get the current moment as an Instant with a call to Instant.now().
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.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.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (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.
First of all, I would recommend to use Calendar instead of Date. I had some problems before, using date.
And I would use the time in milliseconds to compare dates, this is the safest way. The code wuoul be sth like:
Date now = new Date();
long startTimeInMillis = startTime.getTime();
long endTimeInMillis = endTime.getTime();
return now.getTime >= startTimeInMillis && now.getTime < endTimeInMillis;
If you want to ignore the Date and only consider the time of day, consider using Joda-Time's LocalTime, which is designed specifically to hold only the time portion.
Here is an example:
java.util.Date startTime = ... ;
java.util.Date endTime = ... ;
public boolean isNowBetweenDateTime()
{
// get current time
final LocalTime now = new LocalTime();
// convert the java.util.Dates to LocalTimes and then compare
return now.isAfter(LocalTime.fromDateFields(startTime)) &&
now.isBefore(LocalTime.fromDateFields(endTime));
}
This java function returns true if the current time is between two other times. It ignores the year/month/day.
import java.text.*;
import java.util.Date;
public static boolean isNowBetweenHours() throws ParseException
{
String leftBoundaryHours = "01:00:00"; //01:00 hours, military time.(1AM)
String rightBoundaryHours = "14:00:00"; //14:00 hours, military time.(2PM)
//returns true if current time is between
//leftBoundaryHours and rightBoundaryHours.
//This formatter converts a bare string to a date.
DateFormat formatter = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
//add the hand specified time to 1970-01-01 to create left/right boundaries.
Date leftTimeBoundary = formatter.parse("1970-01-01 " + leftBoundaryHours);
Date rightTimeBoundary = formatter.parse("1970-01-01 " + rightBoundaryHours);
//extract only the hours, minutes and seconds from the current Date.
DateFormat extract_time_formatter = new SimpleDateFormat("HH:mm:ss");
//Get the current time, put that into a string, add the 1970-01-01,
Date now = formatter.parse("1970-01-01 " +
extract_time_formatter.format(new Date()));
//So it is easy now, with the year, month and day forced as 1970-01-01
//all you do is make sure now is after left, and now is before right.
if (now.after(leftTimeBoundary) && now.before(rightTimeBoundary))
return true;
else
return false;
}
Invoke the function like this:
try {
System.out.println(isNowBetweenHours());
} catch (ParseException e) {
}
If the current time is after 01:00 hours but before 14:00 hours, it returns true. Else it returns false.
Related
I have an ArrayList of integer numbers that represent day-of-month.For example my list contains 2,8,15(always in increasing order) so it will represent dates 2nd ,8th and 15th of any month.On these dates i have to generate some invoice.So like if I am generating invoice on 15th of any month then i need to get data from some table where date should be between previous invoice date(which is 8 according to arraylist) and 15th.Like if I am generating invoice on 2nd of any month then i need to get data between previous invoice date(which will be 15th of previous month according to arraylist) and 2nd of current month.
So my question is like if my code is running today and date is 2nd then how will i get previous invoice date as java date object.So that i can pass today's date and previous invoice date to filter out and get data from the table.
You need to use java8+ or jodatime. Java 8 adopted jodatime so that's why there's a distinction. Jodatime's api is exactly what you are looking for.
You can just use the following code:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date d = sdf.parse("21/12/2012");
the string that you are parsing, which in this example is "21/12/2012" can be changed to whatever you want.
Hope this helps, if not, let me know what issue you're facing.
Your question is confusing, but I can get you started. I do suggest you rewrite your question to be crystal clear, for your own benefit, to come to understand your problem thoroughly in plain language before you start coding.
First use precise terms to clarify your thinking. You do not start with an ArrayList of date, you have an ArrayList of integer numbers that represent day-of-month.
Next you need today's date. That requires a time zone. For any given moment the date varies around the globe by zone.
ZoneId z = ZoneId.of( "America/Montreal" );
The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate today = LocalDate.now( z );
You might find YearMonth class handy.
YearMonth ym = YearMonth.from( today );
You can get a date from that YearMonth.
LocalDate ld = ym.atDay( 15 );
You can get last day of month.
LocalDate endOfMonth = ym.atEndOfMonth();
You can do math, adding or subtracting months to the YearMonth.
YearMonth previousYm = ym.minusMonths( 1 );
You can retrieve a day-of-month from a LocalDate.
int dayOfMonth = myLocalDate.getDayOfMonth();
You can increment LocalDate with plus and minus methods.
LocalDate nextDate = myLocalDate.plusDays( 1 );
You should be able to put those pieces together to perform your particular business logic.
Tip: Stay away from the troublesome old legacy date-time classes. Use only java.time classes.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.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.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (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.
finally i solved my problem from below code.
private Date getPreviousInvoiceDateFromList(List<String> invoiceDatesList, int dayOfMonth,
int lastDayOfMonth) {
String dayOfMonthStr = String.valueOf(dayOfMonth);
if (invoiceDatesList.size() == 1) {
return new LocalDate().minusMonths(1).toDate();
}
int prevInvoiceDateIndex = -1;
int todaysDateIndex = invoiceDatesList.indexOf(dayOfMonthStr);
if (todaysDateIndex == 0) {
prevInvoiceDateIndex = invoiceDatesList.size() - 1;
String prevInvoiceDate = invoiceDatesList.get(prevInvoiceDateIndex);
int prevInvoiceDateVal = Integer.parseInt(prevInvoiceDate);
int noOfDaysDiff = lastDayOfMonth - prevInvoiceDateVal;
int totalDaysDiff = noOfDaysDiff + dayOfMonth;
return new LocalDate().minusDays(totalDaysDiff - 1).toDate();
} else {
prevInvoiceDateIndex = todaysDateIndex - 1;
String prevInvoiceDate = invoiceDatesList.get(prevInvoiceDateIndex);
int prevInvoiceDateVal = Integer.parseInt(prevInvoiceDate);
int diff = dayOfMonth - prevInvoiceDateVal;
return new LocalDate().minusDays(diff).toDate();
}
}
I trying to calculate a date window based on 3 days prior and after the current plus 30,60,90 days. I really don't no a correct way to do it with calendar this is besides this dirty way.
public static void main(String []args) throws ParseException {
Calendar cal = GregorianCalendar.getInstance();
System.out.println("Curent date is " + cal.getTime() + "\n");
int [] remainingPeriodArr = {30,60,90,180};
int [] expiredArr = {30,60,90};
for(int i = 0; i < remainingPeriodArr.length; i++) {
getSupportPeriod(remainingPeriodArr[i]);
}
for(int i = 0; i < expiredArr.length; i++) {
getSupportPeriod(expiredArr[i]);
}
}
public static void getSupportPeriod(int period) {
Calendar c1 = GregorianCalendar.getInstance();
c1.add(Calendar.DATE, -3);
c1.add(Calendar.DATE, period);
System.out.println( period + " days from prior window " + c1.getTime() + "\n");
Calendar c2 = GregorianCalendar.getInstance();
c2.add(Calendar.DATE, 3);
// Date d2 = c2.getTime();
c2.add(Calendar.DATE, period);
System.out.println( period+ " days in the future window " + c2.getTime() + "\n");
}
}
Barring the new JDK8 date library or Joda Time, the easiest is to work off the current time in milliseconds:
long now = System.currentTimeMilliseconds();
long threeDaysAgoMillis = now - (3 * 24 * 60 * 60 * 1000);
long nowPlus30Millis = now + (30 * 24 * 60 * 60 * 1000);
Date threeDaysAgo = new Date(threeDaysAgoMillis);
Date nowPlus30 = new Date(nowPlus30Millis);
If you're using JDK8, check out this tutorial. If you can use Joda time, look here.
If you go the old JDK way then be aware of following pitfalls:
A) Avoid inherited static methods in general, but use the concrete value object type.
Calendar c1 = GregorianCalendar.getInstance();
Better use:
GregorianCalendar c1 = new GregorianCalendar();
Why? If you are in Thailand you will not get the gregorian calendar with your approach by using a static Calendar-method on GregorianCalendar-class. Instead you get the buddhist calendar.
B) Use domain specific type dependent on your problem
Unfortunately GregorianCalendar is not a date-only type so it does not fit well your requirements for date arithmetic. And in old JDK there is no such type at all so you have to live with ugly work-arounds. In Java 8 you can use java.time.LocalDate, in JodaTime you can use org.joda.time.LocalDate. In my coming time library you can use net.time4j.PlainDate (first release still this month).
C) Otherwise try to mimic a plain date type
Using GregorianCalendar you need to zero out all time fields, that is:
gcal.set(year, month, dayOfMonth);
gcal.set(Calendar.HOUR_OF_DAY, 0);
gcal.set(Calendar.MINUTE, 0);
gcal.set(Calendar.SECOND, 0);
gcal.set(Calendar.MILLISECOND, 0);
Note that this approach is not perfect under some rare conditions related to time zone offset changes, but will probably be sufficient in US and Europe.
If you evaluate such calendar objects as result of addition operations like add(Calendar.DATE, period), you should only print its date part and ignore the time part - in most cases by selecting a date-only format according to your local or as ISO-8601-format (mostly limited to year, month, day-of-month).
If you compare such calendar objects then don't apply comparisons based on the method getTime(), but only by explicit extracting year, month and day-of-month (writing a specialized Comparator is a good idea).
D) Avoid self-made date/time-arithmetic, trust the library
Code like long nowPlus30Millis = now + (30 * 24 * 60 * 60 * 1000); will probably fail if you have a daylight-saving switch in the meantime. The add()-method of java.util.GregorianCalendar can take this in account, but in general not self-made arithmetic.
tl;dr
LocalDate.now().plusDays( 3 )
java.time
The modern approach uses the 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, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
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 ) ;
Math
One way to add days is with the LocalDate::plusDays method. Similar for subtraction.
LocalDate later = ld.plusDays( 3 ) ;
LocalDate earlier = ld.minusDays( 3 ) ;
Or, use objects to represent the span-of-time to be added or subtracted. This has the advantage of being able to label your span-of-time with variable name. For years-months-days, use Period. For hours-minutes-seconds, use Duration.
Period periodBookIsLate = Period.ofDays( 3 ) ;
LocalDate dueDate = ld.plus( periodBookIsLate ) ;
LocalDateRange
You may find the LocalDateRange class useful, available from the ThreeTen-Extra project.
LocalDateRange thirtyDayRange = LocalDateRange.of( ld.minusDays( 30 ) , ld.plusDays( 30 ) ) ;
Learn about the handy methods in that class such as abuts, contains, intersection, and more.
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 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 there a simple or elegant way to grab only the time of day (hours/minutes/seconds/milliseconds) part of a Java Date (or Calendar, it really doesn't matter to me)? I'm looking for a nice way to separately consider the date (year/month/day) and the time-of-day parts, but as far as I can tell, I'm stuck with accessing each field separately.
I know I could write my own method to individually grab the fields I'm interested, but I'd be doing it as a static utility method, which is ugly. Also, I know that Date and Calendar objects have millisecond precision, but I don't see a way to access the milliseconds component in either case.
Edit: I wasn't clear about this: using one of the Date::getTime() or Calendar::getTimeInMillis is not terribly useful to me, since those return the number of milliseconds since the epoch (represented by that Date or Calendar), which does not actually separate the time of day from the rest of the information.
#Jherico's answer is the closest thing, I think, but definitely is something I'd still have to roll into a method I write myself. It's not exactly what I'm going for, since it still includes hours, minutes, and seconds in the returned millisecond value - though I could probably make it work for my purposes.
I still think of each component as separate, although of course, they're not. You can write a time as the number of milliseconds since an arbitrary reference date, or you could write the exact same time as year/month/day hours:minutes:seconds.milliseconds.
This is not for display purposes. I know how to use a DateFormat to make pretty date strings.
Edit 2: My original question arose from a small set of utility functions I found myself writing - for instance:
Checking whether two Dates represent a date-time on the same day;
Checking whether a date is within a range specified by two other dates, but sometimes checking inclusively, and sometimes not, depending on the time component.
Does Joda Time have this type of functionality?
Edit 3: #Jon's question regarding my second requirement, just to clarify: The second requirement is a result of using my Dates to sometimes represent entire days - where the time component doesn't matter at all - and sometimes represent a date-time (which is, IMO, the most accurate word for something that contains year/month/day and hours:minutes:seconds:...).
When a Date represents an entire day, its time parts are zero (e.g. the Date's "time component" is midnight) but the semantics dictate that the range check is done inclusively on the end date. Because I just leave this check up to Date::before and Date::after, I have to add 1 day to the end date - hence the special-casing for when the time-of-day component of a Date is zero.
Hope that didn't make things less clear.
Okay, I know this is a predictable answer, but... use Joda Time. That has separate representations for "a date", "an instant", "a time of day" etc. It's a richer API and a generally saner one than the built-in classes, IMO.
If this is the only bit of date/time manipulation you're interested in then it may be overkill... but if you're using the built-in date/time API for anything significant, I'd strongly recommend that you move away from it to Joda as soon as you possibly can.
As an aside, you should consider what time zone you're interested in. A Calendar has an associated time zone, but a Date doesn't (it just represents an instant in time, measured in milliseconds from the Unix epoch).
Extracting the time portion of the day should be a matter of getting the remainder number of milliseconds when you divide by the number of milliseconds per day.
long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
Date now = Calendar.getInstance().getTime();
long timePortion = now.getTime() % MILLIS_PER_DAY;
Alternatively, consider using joda-time, a more fully featured time library.
Using Calendar API -
Solution 1-
Calendar c = Calendar.getInstance();
String timeComp = c.get(Calendar.HOUR_OF_DAY)+":"+c.get(Calendar.MINUTE)+":"+c.get(Calendar.SECOND)+":"+c.get(Calendar.MILLISECOND);
System.out.println(timeComp);
output - 13:24:54:212
Solution 2-
SimpleDateFormat time_format = new SimpleDateFormat("HH:mm:ss.SSS");
String timeComp = time_format.format(Calendar.getInstance().getTime());
output - 15:57:25.518
To answer part of it, accessing the millisecond component is done like this:
long mill = Calendar.getInstance().getTime();
I don't know what you want to do with the specifics, but you could use the java.text.SimpleDateFormat class if it is for text output.
You can call the getTimeInMillis() function on a Calendar object to get the time in milliseconds. You can call get(Calendar.MILLISECOND) on a calendar object to get the milliseconds of the second. If you want to display the time from a Date or Calendar object, use the DateFormat class. Example: DateFormat.getTimeInstance().format(now). There is also a SimpleDateFormat class that you can use.
To get just the time using Joda-Time, use the org.joda.time.LocalTime class as described in this question, Joda-Time, Time without date.
As for comparing dates only while effectively ignoring time, in Joda-Time call the withTimeAtStartOfDay() method on each DateTime instance to set an identical time value. Here is some example code using Joda-Time 2.3, similar to what I posted on another answer today.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
// http://www.joda.org/joda-time/
// Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
// JSR 310 was inspired by Joda-Time but is not directly based on it.
// http://jcp.org/en/jsr/detail?id=310
// By default, Joda-Time produces strings in the standard ISO 8601 format.
// https://en.wikipedia.org/wiki/ISO_8601
// Capture one moment in time.
org.joda.time.DateTime now = new org.joda.time.DateTime();
System.out.println("Now: " + now);
// Calculate approximately same time yesterday.
org.joda.time.DateTime yesterday = now.minusDays(1);
System.out.println("Yesterday: " + yesterday);
// Compare dates. A DateTime includes time (hence the name).
// So effectively eliminate the time by setting to start of day.
Boolean isTodaySameDateAsYesterday = now.withTimeAtStartOfDay().isEqual(yesterday.withTimeAtStartOfDay());
System.out.println("Is today same date as yesterday: " + isTodaySameDateAsYesterday);
org.joda.time.DateTime halloweenInUnitedStates = new org.joda.time.DateTime(2013, 10, 31, 0, 0);
Boolean isFirstMomentSameDateAsHalloween = now.withTimeAtStartOfDay().isEqual(halloweenInUnitedStates.withTimeAtStartOfDay());
System.out.println("Is now the same date as Halloween in the US: " + isFirstMomentSameDateAsHalloween);
If all you're worried about is getting it into a String for display or saving, then just create a SimpleDateFormat that only displays the time portion, like new SimpleDateFormat("HH:mm:ss"). The date is still in the Date object, of course, but you don't care.
If you want to do arithmetic on it, like take two Date objects and find how many seconds apart they are while ignoring the date portion, so that "2009-09-01 11:00:00" minus "1941-12-07 09:00:00" equals 2 hours, then I think you need to use a solution like Jherico's: get the long time and take it module 1 day.
Why do you want to separate them? If you mean to do any arithmetic with the time portion, you will quickly get into trouble. If you pull out 11:59pm and add a minute, now that your time and day are separate, you've screwed yourself--you'll have an invalid time and an incorrect date.
If you just want to display them, then applying various simple date format's should get you exactly what you want.
If you want to manipulate the date, I suggest you get the long values and base everything off of that. At any point you can take that long and apply a format to get the minutes/hours/seconds to display pretty easily.
But I'm just a little concerned with the concept of manipulating day and time separately, seems like opening a can o' worms. (Not to even mention time zone problems!).
I'm fairly sure this is why Java doesn't have an easy way to do this.
Find below a solution which employs Joda Time and supports time zones.
So, you will obtain date and time (into currentDate and currentTime) in the currently configured timezone in the JVM.
Please notice that Joda Time does not support leap seconds. So, you can be some 26 or 27 seconds off the true value. This probably will only be solved in the next 50 years, when the accumulated error will be closer to 1 min and people will start to care about it.
See also: https://en.wikipedia.org/wiki/Leap_second
/**
* This class splits the current date/time (now!) and an informed date/time into their components:
* <lu>
* <li>schedulable: if the informed date/time is in the present (now!) or in future.</li>
* <li>informedDate: the date (only) part of the informed date/time</li>
* <li>informedTime: the time (only) part of the informed date/time</li>
* <li>currentDate: the date (only) part of the current date/time (now!)</li>
* <li>currentTime: the time (only) part of the current date/time (now!)</li>
* </lu>
*/
public class ScheduleDateTime {
public final boolean schedulable;
public final long millis;
public final java.util.Date informedDate;
public final java.util.Date informedTime;
public final java.util.Date currentDate;
public final java.util.Date currentTime;
public ScheduleDateTime(long millis) {
final long now = System.currentTimeMillis();
this.schedulable = (millis > -1L) && (millis >= now);
final TimeZoneUtils tz = new TimeZoneUtils();
final java.util.Date dmillis = new java.util.Date( (millis > -1L) ? millis : now );
final java.time.ZonedDateTime zdtmillis = java.time.ZonedDateTime.ofInstant(dmillis.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdmillis = java.util.Date.from(tz.tzdate(zdtmillis));
final java.util.Date ztmillis = new java.util.Date(tz.tztime(zdtmillis));
final java.util.Date dnow = new java.util.Date(now);
final java.time.ZonedDateTime zdtnow = java.time.ZonedDateTime.ofInstant(dnow.toInstant(), java.time.ZoneId.systemDefault());
final java.util.Date zdnow = java.util.Date.from(tz.tzdate(zdtnow));
final java.util.Date ztnow = new java.util.Date(tz.tztime(zdtnow));
this.millis = millis;
this.informedDate = zdmillis;
this.informedTime = ztmillis;
this.currentDate = zdnow;
this.currentTime = ztnow;
}
}
public class TimeZoneUtils {
public java.time.Instant tzdate() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tzdate(zdtime);
}
public java.time.Instant tzdate(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final java.time.Instant instant = zddate.toInstant();
return instant;
}
public long tztime() {
final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
return tztime(zdtime);
}
public long tztime(java.time.ZonedDateTime zdtime) {
final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
final long millis = zddate.until(zdtime, java.time.temporal.ChronoUnit.MILLIS);
return millis;
}
}
tl;dr
LocalTime lt = myUtilDate.toInstant().atZone( ZoneId.of( "America/Montreal" ) ).toLocalTime() ;
Avoid old date-time classes
You are using old legacy date-time classes. They are troublesome and confusing; avoid them.
Instead use java.time classes. These supplant the old classes as well as the Joda-Time library.
Convert
Convert your java.util.Date to an Instant.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = myUtilDate.toInstant();
Time Zone
Apply a time zone. Time zone is crucial. 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 also being “yesterday” in Montréal Québec.
Apply a ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
Local… types
The LocalDate class represents a date-only value without time-of-day and without time zone. Likewise, the LocalTime represents a time-of-day without a date and without a time zone. You can think of these as two components which along with a ZoneId make up a ZonedDateTime. You can extract these from a ZonedDateTime.
LocalDate ld = zdt.toLocalDate();
LocalTime lt = zdt.toLocalTime();
Strings
If your goal is merely generating Strings for presentation to the user, no need for the Local… types. Instead, use DateTimeFormatter to generate strings representing only the date-portion or the time-portion. That class is smart enough to automatically localize while generating the String.
Specify a Locale to determine (a) the human language used for translating name of day, name of month, and such, and (b) the cultural norms for deciding issues such as abbreviation, capitalization, punctuation, and such.
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.ITALY, etc.
DateTimeFormatter fDate = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale );
String outputDate = zdt.format( fDate );
DateTimeFormatter fTime = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ).withLocale( locale );
String outputTime = zdt.format( fTime );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.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.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (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.