开发者

How to check if a date Object equals yesterday?

开发者 https://www.devze.com 2023-01-03 01:26 出处:网络
Right now I am using this code Calendar cal = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat(\"yyyy-MM-dd\");

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(开发者_如何学Python) is yesterday's date. Only the date matters, not the time. That's why I used SimpleDateFormat. Thanks for your help in advance!


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.


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


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.


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?

  • 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….


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.


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 :(


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 


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.


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)
}
0

精彩评论

暂无评论...
验证码 换一张
取 消