0

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");

}

}

  • 1
    What? Could you please read again your question and/or use google translator atleast? – Reinherd Feb 06 '14 at 15:25
  • What is the problem with what you are doing apart from it being a bit ugly? – mikea Feb 06 '14 at 15:26
  • It seems like your code works. What makes you think this isn't a "correct" way? – dcsohl Feb 06 '14 at 15:28
  • Just thought there could be a better way i'm not an expert :-) – user2131785 Feb 06 '14 at 15:32
  • @user2131785 There may well be a better way, but I cannot make sense of the business problem you are trying to solve. Can explain your goal? The [Joda-Time](http://www.joda.org/joda-time/) framework offers classes to handle a span of time (Interval, Period, and Duration). They be helpful but I cannot determine that without a better explanation. – Basil Bourque Feb 07 '14 at 08:22

3 Answers3

0

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.

Rob Crawford
  • 536
  • 1
  • 5
  • 9
  • Thanks Meno now i am totally lost. I need to find this range and then check to see if a specific date falls into that range. – user2131785 Feb 06 '14 at 16:35
0

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.

Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126
0

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?

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154