向 Java 日历添加年份不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3883167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 03:50:08  来源:igfitidea点击:

Add year to Java Calendar doesn't work

javacalendar

提问by codea

Please enlight me on this :

请让我明白这一点:

I'm simply trying to add 10 years to the current date then substract an expiration date from it to return the number of years:

我只是想将 10 年添加到当前日期,然后从中减去到期日期以返回年数:

public int getMaxYears() {
  int max = 0;
  Calendar ten_year_later = Calendar.getInstance();
  ten_year_later.setTime(new Date());
  ten_year_later.add(Calendar.YEAR, 10);
  Calendar expiration = Calendar.getInstance();
  expiration.setTime(expiration_date);
  max = (int) (ten_year_later.getTimeInMillis() - expiration.getTimeInMillis())/(365 * 24 * 60 * 60 * 1000);
  return max;
}

When I debug this, the calendar always stay at the current year.

当我调试这个时,日历总是停留在当前年份。

Anyone ?

任何人 ?

回答by stacker

You have a problem with int / long conversion: 365 * 24 * 60 * 60 * 1000 Which evaluates to 31536000000 and therefore exceeds Integer.MAX_VALUE2147483647 This works:

你有 int / long 转换的问题:365 * 24 * 60 * 60 * 1000 其计算结果为 31536000000,因此超过Integer.MAX_VALUE2147483647 这有效:

public static void main(String[] args) {
          Calendar ten_year_later = Calendar.getInstance();
          System.out.println( ten_year_later.getTime() );
          ten_year_later.setTime(new Date()); 
          ten_year_later.add(Calendar.YEAR, 10);
          System.out.println( ten_year_later.getTime() );
          Calendar expiration = Calendar.getInstance(); 
          expiration.setTime(expiration.getTime()); 
          long max = (ten_year_later.getTimeInMillis() - expiration.getTimeInMillis())/(365 * 24 * 60 * 60 * 1000L); 
          System.out.println( "max " + max );
        } 

回答by BalusC

Your calculation of maxis wrong. An intcannot hold a year in millis.

你的计算max是错误的。一个int不能以毫秒每年举行。

Rather replace it by

而是将其替换为

max = ten_year_later.get(Calendar.YEAR) - expiration.get(Calendar.YEAR);

Or better, use JodaTime:

或者更好,使用JodaTime

DateTime tenYearsLater = new DateTime().plusYears(10);
DateTime expiration = new DateTime(expiration_date.getTime());
Period period = new Period(expiration, tenYearsLater);
return period.getYears();

回答by Bryan James

Here's a simple example of what should work.

这是一个简单的例子,说明什么应该起作用。

Calendar cal = new GregorianCalendar();
cal.setTime(new Date());
cal.add(Calendar.YEAR, yearsToAdd);
Date retDate = cal.getTime();

Just remember to use a long to get the time in milliseconds!

请记住使用 long 来获取以毫秒为单位的时间!

回答by Paul Tomblin

Calendar is lazy, so it might not recalculate all the other fields until you ask for them. That's thrown me off in the debugger before. What happens if you System.out.println(ten_year_later);?

Calendar 是惰性的,因此在您要求之前它可能不会重新计算所有其他字段。那之前在调试器中让我失望了。如果你这样做会System.out.println(ten_year_later);怎样?

回答by Anon

I've noted in a comment that you have an incorrect calculation for number of millis in a year (nevermind the int/long issue).

我在评论中指出,您对一年中的毫秒数的计算不正确(更不用说 int/long 问题了)。

Since you have two calendars, each of which can keep a year, why don't you write your code like this (not compiled, so may contain typos):

既然你有两个日历,每个日历可以保存一年,你为什么不这样写你的代码(没有编译,所以可能有错别字):

Calendar cal1 = Calendar.newInstance();   // this will use current time
cal1.add(Calendar.YEAR, 10);
Calendar cal2 = Calendar.newInstance();
cal2.setDate(expiration);
return cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR);

Assuming that's what you really want ...

假设这就是你真正想要的......

回答by Basil Bourque

tl;dr

tl;博士

Use modern java.timeclasses. Can be done in a one-liner (not that I recommend that).

使用现代java.time类。可以单线完成(不是我推荐的)。

Period
.between(
    ( ( GregorianCalendar) myCalendarExpiration ).toZonedDateTime().toLocalDate() ,
    ZonedDateTime.now( ZoneId.of( "Asia/Kolkata" ) ).plusYears( 10 ).toLocalDate() 
)
.getYears()

java.time

时间

The modern approach uses the java.timeclasses that supplanted the legacy date-time classes such as Calendar.

现代方法使用java.time类取代了传统的日期时间类,例如Calendar.

The usual concrete implementation of Calendaris GregorianCalendar. This is now replaced by ZonedDateTime. You can convert back and forth by calling new methods on the old classes.

通常的具体实现CalendarGregorianCalendar。现在由ZonedDateTime. 您可以通过在旧类上调用新方法来来回转换。

ZonedDateTime zdtExpiration = ( ( GregorianCalendar) myCal ).toZonedDateTime() ;

Get current moment.

获取当前时刻。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdtNow  = ZonedDateTime.now( z ) ;

Add ten years.

加上十年。

ZonedDateTime zdtLater = zdtNow.plusYears( 10 ) ;

Calculate elapsed time in years between the dates of those two moments.

计算这两个时刻的日期之间经过的时间(以年为单位)。

Period p = Period.between(
    zdtExpiration.toLocalDate() , 
    zdtLater.toLocalDate()
) ;

Interrogate for the number of full years.

询问完整的年数。

int yearsElapsed = p.getYears() ;


About java.time

关于java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如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.

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

现在处于维护模式Joda-Time项目建议迁移到java.time类。

You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*classes.

您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject 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.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

回答by jarnbjo

The number of milliseconds in a year is well outside the range of an int, so both the int cast of ten_year_later.getTimeInMillis() - expiration.getTimeInMillis()and the calculation 365 * 24 * 60 * 60 * 1000will evaluate to incorrect values.

一年中的毫秒数远远超出 int 的范围,因此 int 类型转换ten_year_later.getTimeInMillis() - expiration.getTimeInMillis()和计算365 * 24 * 60 * 60 * 1000都将评估为不正确的值。

The ten_year_latershould be correct. There is no need to invoke computeFields as R. Bemrose wrote.

ten_year_later应该是正确的。不需要像 R. Bemrose 写的那样调用 computeFields。