How to check if a date Object equals yesterday?
Asked Answered
S

9

47

Right now I am using this code

Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE) - 1, 12, 0, 0); //Sets Calendar to "yeserday, 12am"
if(sdf.format(getDateFromLine(line)).equals(sdf.format(cal.getTime())))                         //getDateFromLine() returns a Date Object that is always at 12pm
{...CODE

There's got to be a smoother way to check if the date returned by getdateFromLine() is yesterday's date. Only the date matters, not the time. That's why I used SimpleDateFormat. Thanks for your help in advance!

Singlehanded answered 9/6, 2010 at 13:21 Comment(0)
A
91
Calendar c1 = Calendar.getInstance(); // today
c1.add(Calendar.DAY_OF_YEAR, -1); // yesterday

Calendar c2 = Calendar.getInstance();
c2.setTime(getDateFromLine(line)); // your date

if (c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR)
  && c1.get(Calendar.DAY_OF_YEAR) == c2.get(Calendar.DAY_OF_YEAR)) {

This will also work for dates like 1st of January.

Alexandro answered 9/6, 2010 at 13:50 Comment(3)
Why does this work for the 1st of January? Won't the year be different for December 31?Labrum
It works because Calendar.add changes the timestamp of the date by an offset computed from the type of the field and the amount inputted. So no matter the original date, it only uses the timestamp (milliseconds since 1st Jan 1970) and computes the new date based on that plus/minus the difference computed for the input. This in effect will change the year as well, even though the field is DAY_OF_YEAR.Alexandro
anyone seeing this thread should refer to @Przemek's answer, which uses java.time, which should be used in preference to joda-time, java.util.Date, and java.util.Calendar: https://mcmap.net/q/152557/-how-to-check-if-a-date-object-equals-yesterdayHouseline
A
25

java.time

Using java.time framework built into Java 8

LocalDate now = LocalDate.now(); //2015-11-24
LocalDate yesterday = LocalDate.now().minusDays(1); //2015-11-23

yesterday.equals(now); //false
yesterday.equals(yesterday); //true

Official Oracle LocalDate tutorial states

The equals method should be used for comparisons.

If you're working with objects such as LocalDateTime, ZonedDateTime, or OffsetDateTime, you may convert to LocalDate.

LocalDateTime.now().toLocalDate(); # 2015-11-24
Abduce answered 24/11, 2015 at 11:59 Comment(1)
I suggest always passing the optional ZoneId to LocalDate.now rather than rely implicitly on the JVM’s current default time zone. That default can change at any moment even during runtime. Like this: LocalDate.now( ZoneId.of( "America/Montreal" ) )Fleda
D
14

I agree with Ash Kim that the Joda-Time library is the way to go if you want to preserve your sanity.

import org.joda.time.DateTime;

public static boolean dayIsYesterday(DateTime day) {
    DateTime yesterday = new DateTime().withTimeAtStartOfDay().minusDays(1);
    DateTime inputDay = day.withTimeAtStartOfDay();

    return inputDay.isEqual(yesterday);
}

In this example, if the DateTime day is from yesterday then dayIsYesterday(day) will return true.

Dyun answered 23/3, 2011 at 21:51 Comment(5)
The midnight-related classes and methods in Joda-Time were based on a flawed idea. They are now deprecated as of Joda-Time 2.3. Instead use the method withTimeAtStartOfDay.Fleda
Also, you should generally specify time zone rather than rely on JVM's default as that is critical to determining "today" and "yesterday".Fleda
now = "1/07/2016". previous = "12/06/1980". Your previousFromYesteray will be set to true, while the topic starter asked about how you can check if a date is "yesterday".Exacerbate
@Exacerbate good point. Edited. 2011 me has some explaining to do.Dyun
@Dyun there's even more room for improvement :) You use DateTime which makes sense but for this particular task LocalDate from JodaTime will do just perfect.Exacerbate
F
9

Avoid java.util.Date & .Calendar

The accepted answer is technically correct but less than optimal. The java.util.Date and .Calendar classes are notoriously troublesome. Avoid them. Use either Joda-Time or the new java.time package (in Java 8).

Time Zone

Time zone is critical in date-time work. If you ignore the issue, the JVM's default time zone will be applied. A better practice is to always specify rather than rely on default. Even when you want the default, explicitly call getDefault.

The beginning of the day is defined by the time zone. A new day dawns earlier in Berlin than in Montréal. So the definition of "today" and "yesterday" requires a time zone.

Joda-Time

Example code in Joda-Time 2.3.

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Berlin" );
DateTime today = DateTime.now( timeZone ); 

One way to determine yesterday is by converting to LocalDate objects. Another way, shown here, is to represent "yesterday" as a span of time. We define that span as going from the first moment of yesterday up to but not including the first moment of today. This approach is called "half-open" where the beginning is inclusive and the ending is exclusive.

Subtract a day to get to yesterday (or day before).

DateTime yesterdayStartOfDay = today.minusDays( 1 ).withTimeAtStartOfDay();
Interval yesterdayInterval = new Interval( yesterdayStartOfDay, today.withTimeAtStartOfDay() );

Convert your target java.util.Date object to a Joda-Time DateTime object. Apply a time zone to that new object, rather than rely on applying JVM's default time zone. Technically the time zone here in this case is irrelevant, but including a time zone is a good habit.

DateTime target = new DateTime( myJUDate, timeZone );

Test if the target lands within the interval of yesterday.

boolean isYesterday = yesterdayInterval.contains( target );

Obviously this approach with half-open span of time works with more than just "yesterday", such as "this week", "last month", and so on.

Updated: The Joda-Time project is now in maintenance mode. The team advises migration to the java.time classes. See the java.time solution in the correct Answer by Przemek.


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?

Fleda answered 13/6, 2014 at 20:48 Comment(0)
I
3

Instead of setting the calendar try this:

public static void main(String[] args) {
    int DAY_IN_MILLIS = 1000 * 60 * 60 * 24;
    Date date = new Date();
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yy");
    String prevDate = dateFormat.format(date.getTime() - DAY_IN_MILLIS);
    String currDate = dateFormat.format(date.getTime());
    String nextDate = dateFormat.format(date.getTime() + DAY_IN_MILLIS);
    System.out.println("Previous date: " + prevDate);
    System.out.println("Current date: " + currDate);
    System.out.println("Next date: " + nextDate);
  }

This should allow you to move forwards and backwards along the calendar

Then you can simply compare the getDateFromLine(line) to the prevDate value or whatever you like.

Iridotomy answered 9/6, 2010 at 13:29 Comment(0)
L
1

Something like this roughly:

         Calendar c1 = Calendar.getInstance();
         Date d1 = new Date(/* control time */);
         c1.setTime(d1);

        //current date
        Calendar c2 = Calendar.getInstance();

        int day1=c1.get(Calendar.DAY_OF_YEAR);
        int day2=c2.get(Calendar.DAY_OF_YEAR);

       //day2==day1+1 
Lintwhite answered 9/6, 2010 at 13:45 Comment(2)
Should also compare the year values as well.Tyner
oh yes i forgot about the year.Lintwhite
W
1

I have found it a little confuse when I use this way to test this method

 Calendar now = new GregorianCalendar(2000, 1, 1);
 now.add(Calendar.DATE, -1);

 SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd");
 System.out.println(format.format(now.getTime()));

my expect is to print 1999-12-31,but the actual is 2001-1-31 I guess Calendar.add() only deal with day in month.

But the actual error is the way I create the Calendar object. In Calendar ,month start with 0,the variable now's value is 2001-2-1, I was so self-conceit as not to print it.when I found something was wrong. correct way to create a Calendar is :

 Calendar now = new GregorianCalendar(2000, Calendar.JANUARY, 1);

The Calendar was so weird to an ex C# programmer :(

Waring answered 17/4, 2015 at 6:1 Comment(0)
F
1

The highest voted answer uses legacy java.util date-time API which was the correct thing to do in 2010 when the question was asked. In March 2014, java.time API supplanted the error-prone legacy date-time API. Since then, it is strongly recommended to use this modern date-time API.

Ways to get yesterday's date:

There are three ways:

  1. LocalDate#minusDays(long daysToSubtract)
  2. LocalDate#minus(long amountToSubtract, TemporalUnit unit): It has got some additional capabilities e.g. you can use it to decrement a local date by days, weeks, months, years etc.
  3. LocalDate#minus(TemporalAmount amountToSubtract): You can specify a Period (or any other type implementing the TemporalAmount) to subtract.

Once you have yesterday's date, you can use LocalDate#isEqual to check if it is equal to the given local date.

Demo:

import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;

public class Main {
    public static void main(String[] args) {
        // Note: Replace the default ZoneId with the required ZoneId e.g. ZoneId.of("Europe/London")
        LocalDate today = LocalDate.now(ZoneId.systemDefault());
        System.out.println(today);

        // Decrementing by one day
        LocalDate yesterday = today.minusDays(1);
        System.out.println(yesterday);

        // Alternatively
        yesterday = today.minus(1, ChronoUnit.DAYS);
        System.out.println(yesterday);

        // or
        yesterday = today.minus(Period.ofDays(1));
        System.out.println(yesterday);

        // A sample LocalDate
        LocalDate givenDate = LocalDate.of(2022, 10, 20);

        // Check for equality
        System.out.println(givenDate.isEqual(yesterday));
        givenDate = yesterday;
        System.out.println(givenDate.isEqual(yesterday)); // true
    }
}

Output:

2022-11-13
2022-11-12
2022-11-12
2022-11-12
false
true

How to switch from the legacy to the modern date-time API?

You can switch from the legacy to the modern date-time API using Date#toInstant on a java-util-date instance. Once you have an Instant, you can easily obtain other date-time types of java.time API. An Instant represents a moment in time and is independent of a time-zone i.e. it represents a date-time in UTC (often displayed as Z which stands for Zulu-time and has a ZoneOffset of +00:00).

Demo:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        Date date = new Date();
        Instant instant = date.toInstant();
        System.out.println(instant);

        ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Kolkata"));
        System.out.println(zdt);

        OffsetDateTime odt = instant.atOffset(ZoneOffset.of("+05:30"));
        System.out.println(odt);
        // Alternatively, using time-zone
        odt = instant.atZone(ZoneId.of("Asia/Kolkata")).toOffsetDateTime();
        System.out.println(odt);

        LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.of("Asia/Kolkata"));
        System.out.println(ldt);
        // Alternatively,
        ldt = instant.atZone(ZoneId.of("Asia/Kolkata")).toLocalDateTime();
        System.out.println(ldt);
    }
}

Output:

2022-11-13T21:08:36.538Z
2022-11-14T02:38:36.538+05:30[Asia/Kolkata]
2022-11-14T02:38:36.538+05:30
2022-11-14T02:38:36.538+05:30
2022-11-14T02:38:36.538
2022-11-14T02:38:36.538

Learn more about the modern Date-Time API from Trail: Date Time.

Fogdog answered 13/11, 2022 at 21:9 Comment(0)
B
0

Feel free to reuse these extension methods. They were very influenced by this post answers. Thanks to everyone, by the way!

fun Date.isSameDay(other: Date): Boolean {
    val thisCalendar = Calendar.getInstance()
    val otherCalendar = Calendar.getInstance()
    thisCalendar.time = this
    otherCalendar.time = other
    return thisCalendar.get(Calendar.YEAR) == otherCalendar.get(Calendar.YEAR)
            && thisCalendar.get(Calendar.DAY_OF_YEAR) == otherCalendar.get(Calendar.DAY_OF_YEAR)
}

fun Date.isYesterday(other: Date): Boolean {
    val yesterdayCalendar = Calendar.getInstance()
    yesterdayCalendar.time = other
    yesterdayCalendar.add(Calendar.DAY_OF_YEAR, -1)

    return yesterdayCalendar.time.isSameDay(this)
}
Berliner answered 27/7, 2020 at 15:0 Comment(4)
These terrible date-time classes were supplanted years ago by the modern java.time classes defined in JSR 310.Fleda
Don't hate them. On Android, you have to deal with these terrible data-time classes until you support only Android 26 and above or depend on third-party libraries. Let's respect those poor old and deprecated classes. They are still useful.Berliner
Nope, no need at all for the terrible legacy classes. Gradle Plug-in 4 now provides a “API desugaring” feature to retroactively use a subset of the java.time classes with older Android. And if that does not do it for you, use the ThreeTen-Backport project adapted to Android in the ThreeTenABP library. See links at bottom of my Answer.Fleda
Yap, I was adding the ThreeTenABP library to the project when I realized I don't want to add another third party library just to make this comparison... About the Gradle Plugin 4 API desugaring, maybe I try! But this piece of code passes the large amount of tests I wrote to check the feature so... maybe I don't. But perhaps in another project 😄 Thanks a lot for the comment!Berliner

© 2022 - 2025 — McMap. All rights reserved.