简体   繁体   中英

How to Shift Calendar in Java?

I am trying to write a Java method to shift a Calendar, using a time offset in milliseconds. But when I try to shift for one month (30 days) it does not work:

Calendar c = new GregorianCalendar(2012, 5, 23, 13, 23, 10);
long original = c.getTimeInMillis();
System.out.println("Original Date "+c.getTime());

long oneMonth = 30*24*60*60*1000;   //one month in milliseconds
Calendar c_1Month = new GregorianCalendar();
c_1Month.setTimeInMillis(original+oneMonth);
System.out.println("After 1-month "+c_1Month.getTime());

The output is

Original Date Sat Jun 23 13:23:10 PDT 2012
After 1-month Sun Jun 03 20:20:22 PDT 2012

You can see that it does not shift it correctly to July 23rd. I understand there is a specific method add(field, amount) in Calendar and I can change month using that, but I wanna have one single method in my client to shift time, with providing shift amount in milliseconds (the amount of shift changes based on my tests, and I do not want to have several methods for that).

You think the variable oneMonth is a long, but you assign it an integer value. But the result of 30*24*60*60*1000 doesn't fit into an integer and therefore overflows to a negative value.

If you change your code to long oneMonth = 30*24*60*60*1000L; it would work.

But despite of that "bug" in your code the comment of azurefrog is correct, this is not the recommended way to add one month, it would only be valid in case you like to add 30 days which is something different.

Try to use something like this instead:

c_1Month.add( Calendar.DAY_OF_MONTH, 30);

or

c_1Month.add( Calendar.MONTH, 1);

The Calendar class is aware and able to handle all corner cases very good. I would suggest you rely on this. It reduces possible bugs and makes code easier to read and understand.

With Java 8 the code to use would be:

LocalDateTime.now().plusMonths(1);

or

LocalDateTime.now().plusDays(30);

Add an "L" at the end of 30*24*60*60*1000

The way you are calculating, you are transforming the whole thing into an INTEGER.

Don't believe me :), try printing the value before adding the L after the 1000;

    System.out.println(oneMonth);

Your final code should be:

    Calendar c = new GregorianCalendar(2012, 5, 23, 13, 23, 10);
    long original = c.getTimeInMillis();
    System.out.println("Original Date "+c.getTime());

    long oneMonth = 30*24*60*60*1000L;   //one month in milliseconds

    Calendar c_1Month = new GregorianCalendar();
    c_1Month.setTimeInMillis(original+oneMonth);
    System.out.println("After 1-month "+c_1Month.getTime());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM