daveb
daveb

Reputation: 3535

I want to get Year, Month, Day, etc from Java Date to compare with Gregorian Calendar date in Java. Is this possible?

I have a Date object in Java stored as Java's Date type.

I also have a Gregorian Calendar created date. The gregorian calendar date has no parameters and therefore is an instance of today's date (and time?).

With the java date, I want to be able to get the year, month, day, hour, minute, and seconds from the java date type and compare the the gregoriancalendar date.

I saw that at the moment the Java date is stored as a long and the only methods available seem to just write the long as a formatted date string. Is there a way to access Year, month, day, etc?

I saw that the getYear(), getMonth(), etc. methods for Date class have been deprecated. I was wondering what's the best practice to use the Java Date instance I have with the GregorianCalendar date.

My end goal is to do a date calculation so that I can check that the Java date is within so many hours, minutes etc of today's date and time.

I'm still a newbie to Java and am getting a bit puzzled by this.

Upvotes: 283

Views: 684561

Answers (9)

Basil Bourque
Basil Bourque

Reputation: 340090

tl;dr

check that the Java date is within so many hours, minutes etc of today's date and time

Use java.time classes, never legacy classes. Convert as needed.

For a java.util.Date object:

Duration.between( 
        myJavaUtilDate.toInstant() , 
        Instant.now() 
)
.abs()
.toNanos()
>
Duration.ofHours( 36 ).toNanos()

For a java.util.GregorianCalendar object:

Duration.between( 
        myGregorianCalendar.toZonedDateTime().toInstant() , 
        Instant.now() 
)
.abs()
.toNanos()
>
Duration.ofHours( 36 ).toNanos()

java.util.Date versus GregorianCalendar

Firstly, be aware of two Date classes: java.util.Date & java.sql.Date. Apparently you had the first one in mind.

You said:

With the java date, I want to be able to get the year, month, day, hour, minute, and seconds from the java date type and compare the the gregoriancalendar date.

Let's be clear on what java.util.Date & GregorianCalendar classes each represent. They both represent a moment, a specific point on the timeline. But they have different perspectives on that moment.

  • java.util.Date
    Represents a date with time-of-day as seen with an offset of zero. This is the time you see when you look up at the Shepherd Gate Clock at the Royal Observatory, Greenwich.
  • GregorianCalendar
    Represents a date with time-of-day as seen from the wall-clock/calendar of a particular time zone.

Defining these terms:

  • Offset
    Merely a number of hours-minutes-seconds ahead or behind the temporal meridian of UTC.
  • Time Zone
    A named history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians.

Avoid legacy date-time classes

Both java.util.Date and GregorianCalendar (and Calendar, SimpleDateFormat, etc.) are terribly flawed. Never use them. They have been supplanted by the modern java.time classes built into Java 8 and later.

Legacy class Modern class
java.util.Date java.time.Instant
java.util.GregorianCalendar java.time.ZonedDateTime

When handed an object of either legacy class, immediately convert. Use the new conversion methods added to the old classes .

Instant instan = myJavaUtilDate.toInstant() ;
ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime() ;

If handed a Calendar object, most likely that object is actually a GregorianCalendar. Test with instanceOf to verify, then cast.

if( myCalendar instanceOf GregorianCalendar ) 
{
    GregorianCalendar gc = ( GregorianCalendar ) myCalendar ;
    ZonedDateTime zdt = gc.toZonedDateTime() ;
}

Back to your Question:

I want to get Year, Month, Day, etc from Java Date to compare with Gregorian Calendar date in Java. Is this possible?

Keep in mind that for any given moment, the time-of-day and the date(!) vary around the globe by time zone. For any moment, it will be “tomorrow” in Tokyo Japan while simultaneously “yesterday” in Toledo Ohio US.

Hopefully you can see how tricky is your Question. You can get the date & time from your java.util.Date but do you want the date & time as seen in UTC (at the clock a the Royal Observatory)? Or do you want to adjust that moment to get the date and time-of-day as seen from the time zone as was used in your GreporianCalendar (now a ZonedDateTime)? Both are valid desires, so let's cover each of them.

Comparing UTC to a particular time zone

To extract the year, month, and day from our Instant object, we have to take an extra step. The Instant class is the basic-building block of java.time. For more features and flexibility, we need to convert from Instant to java.time.OffsetDateTime. In doing so we must specify the offset to use. Since our goal here is to view the date & time from the point of view of UTC (offset of zero), we use the constant ZoneOffset.UTC representing an offset of zero.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;

Now we can get the year, month, and date.

int yearX = odt.getYear() ;
int monthX = odt.getMonthValue() ; 
int dayX = odt.getDayOfMonth() ;

Or perhaps you just want to extract the entire date as a LocalDate object.

LocalDate ldX = odt.toLocalDate() ;

Now let's get the same values from our ZonedDateTime object.

int yearY = zdt.getYear() ;
int monthY = zdt.getMonthValue() ; 
int dayY = zdt.getDayOfMonth() ;

Or extract a LocalDate.

LocalDate ldY = zdt.toLocalDate() ;

Adjusting from UTC to a time zone

Now let's try the other approach, adjusting our moment as seen in UTC (an Instant or java.util.Date) to a particular time zone.

To use the same time zone as was used in our ZonedDateTime (originally a GregorianCalendar), we simply interrogate to extract a ZoneId object.

ZoneId z = zdt.getZone() ;

Then apply to our Instant object to get another ZonedDateTime object.

ZonedDateTime zdt2 = instant.atZone( z ) ;

Now you can extract the year, month, day from zdt2 using the same way we did from zdt in code above.

Calculating elapsed time

You said:

My end goal is to do a date calculation so that I can check that the Java date is within so many hours, minutes etc of today's date and time.

Well, you should have said so up front! All the work we did extracting year, month, & day from our objects is irrelevant. The java.time classes can easily calculate the span of time between two moments.

Let's capture the current moment, as seen in UTC.

Instant now = Instant.now() ;

To represent a span of time on the scale of hours-minutes-seconds as you requested, use Duration class.

First, we do a comparison using the Instant object we converted from a java.util.Date.

Duration duration = Duration.between( instant , now ) ;

You can ask isNegative or isPositive to see if the direction between those two moments is going into the past or towards the future.

Second, we do a comparison with the ZonedDateTime object we converted from a GregorianCalendar object. To do this, we can adjust from our time zone to UTC by extracting an Instant from ZonedDateTime.

Duration duration = Duration.between( zdt.toInstant() , now ) ;

You asked "is within so many hours, minutes etc". So define a Duration to specify your limit.

Duration limit = Duration.ofHours( 36 ) ;

Test.

if ( duration.toNanos() > limit.toNanos() ) { … beyond limit … }

You might want to add a call to Duration#abs to handle negative and positive durations in the same manner.

if ( duration.abs().toNanos() > limit.abs().toNanos() ) { … beyond limit … }

Upvotes: 2

Ortomala Lokni
Ortomala Lokni

Reputation: 62683

With Java 8 and later, you can convert the Date object to a LocalDate object and then easily get the year, month and day.

import java.util.Date;
import java.time.LocalDate
import java.time.ZoneId

Date date = new Date();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
int year  = localDate.getYear();
int month = localDate.getMonthValue();
int day   = localDate.getDayOfMonth();

Note that getMonthValue() returns an int value from 1 to 12.

Upvotes: 129

Florent Guillaume
Florent Guillaume

Reputation: 8368

Use something like:

Date date; // your date
// Choose time zone in which you want to interpret your Date
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Paris"));
cal.setTime(date);
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
// etc.

Beware, months start at 0, not 1.

Edit: Since Java 8 it's better to use java.time.LocalDate rather than java.util.Calendar. See this answer for how to do it.

Upvotes: 619

javaCity
javaCity

Reputation: 4318

You could do something like this, it will explain how the Date class works.

String currentDateString = "02/27/2012 17:00:00";
SimpleDateFormat sd = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Date currentDate = sd.parse(currentDateString);

String yourDateString = "02/28/2012 15:00:00";
SimpleDateFormat yourDateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

Date yourDate = yourDateFormat.parse(yourDateString);

if (yourDate.after(currentDate)) {
    System.out.println("After");
} else if(yourDate.equals(currentDate)) {
    System.out.println("Same");
} else {
    System.out.println("Before");
}

Upvotes: 14

rabi
rabi

Reputation: 101

    Date queueDate = new SimpleDateFormat("yyyy-MM-dd").parse(inputDtStr);
    Calendar queueDateCal = Calendar.getInstance();
    queueDateCal.setTime(queueDate);
    if(queueDateCal.get(Calendar.DAY_OF_YEAR)==Calendar.getInstance().get(Calendar.DAY_OF_YEAR))
{
    "same day of the year!";
 }

Upvotes: 3

Az.MaYo
Az.MaYo

Reputation: 1106

    Date date = new Date();

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE");

    System.out.println("DAY "+simpleDateFormat.format(date).toUpperCase());

    simpleDateFormat = new SimpleDateFormat("MMMM");
    System.out.println("MONTH "+simpleDateFormat.format(date).toUpperCase());

    simpleDateFormat = new SimpleDateFormat("YYYY");
    System.out.println("YEAR "+simpleDateFormat.format(date).toUpperCase());

EDIT: The output for date = Fri Jun 15 09:20:21 CEST 2018 is:

DAY FRIDAY
MONTH JUNE
YEAR 2018

Upvotes: 14

Abdur Rahman
Abdur Rahman

Reputation: 1666

It might be easier

     Date date1 = new Date("31-May-2017");
OR
    java.sql.Date date1 = new java.sql.Date((new Date()).getTime());

    SimpleDateFormat formatNowDay = new SimpleDateFormat("dd");
    SimpleDateFormat formatNowMonth = new SimpleDateFormat("MM");
    SimpleDateFormat formatNowYear = new SimpleDateFormat("YYYY");

    String currentDay = formatNowDay.format(date1);
    String currentMonth = formatNowMonth.format(date1);
    String currentYear = formatNowYear.format(date1);

Upvotes: 4

Tiina
Tiina

Reputation: 4797

@Test
public void testDate() throws ParseException {
    long start = System.currentTimeMillis();
    long round = 100000l;
    for (int i = 0; i < round; i++) {
        StringUtil.getYearMonthDay(new Date());
    }
    long mid = System.currentTimeMillis();
    for (int i = 0; i < round; i++) {
        StringUtil.getYearMonthDay2(new Date());
    }
    long end = System.currentTimeMillis();
    System.out.println(mid - start);
    System.out.println(end - mid);
}

public static Date getYearMonthDay(Date date) throws ParseException {
    SimpleDateFormat f = new SimpleDateFormat("yyyyyMMdd");
    String dateStr = f.format(date);
    return f.parse(dateStr);
}

public static Date getYearMonthDay2(Date date) throws ParseException {
    Calendar c = Calendar.getInstance();
    c.setTime(date);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.HOUR_OF_DAY, 0);
    return c.getTime();
}
public static int compare(Date today, Date future, Date past) {
    Date today1 = StringUtil.getYearMonthDay2(today);
    Date future1 = StringUtil.getYearMonthDay2(future);
    Date past1 = StringUtil.getYearMonthDay2(past);
    return today.compare // or today.after or today.before
}

getYearMonthDay2(the calendar solution) is ten times faster. Now you have yyyy MM dd 00 00 00, and then compare using date.compare

Upvotes: 2

evya
evya

Reputation: 3647

private boolean isSameDay(Date date1, Date date2) {
    Calendar calendar1 = Calendar.getInstance();
    calendar1.setTime(date1);
    Calendar calendar2 = Calendar.getInstance();
    calendar2.setTime(date2);
    boolean sameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
    boolean sameMonth = calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
    boolean sameDay = calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH);
    return (sameDay && sameMonth && sameYear);
}

Upvotes: 9

Related Questions