我需要在今年的同一天。
示例:现在是2019年,并且变量包含2022年7月15日的值,因此我需要获取2019年7月15日。它适用于所有日期,除了2月(一年中有一天额外的一天,而今年没有这一天),例如:2020年2月29日将在第二天返回我:2019年3月1日,但在这种情况下,我需要返回前一天:2019年2月28日。如何调整逻辑以使其以这种方式工作?
public static java.util.Date getThisDateInThisYear(java.util.Date date) {
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(date);
Date today = new Date();
GregorianCalendar gcToday = new GregorianCalendar();
gcToday.setTime(today);
gc.set(GregorianCalendar.YEAR, gcToday.get(GregorianCalendar.YEAR));
return gc.getTime();
}
答案 0 :(得分:2)
首先计算年份差,并将结果添加到日期
public Date getThisDateInThisYear(Date date) {
Calendar c = Calendar.getInstance();
int thisYear = c.get(Calendar.YEAR)
c.setTime(date);
int diff = thisYear - c.get(Calendar.YEAR);
c.add(Calendar.YEAR, diff);
return c.getTime();
}
我使用2016-02-29和2020-02-29进行了测试,都返回2019-02-28。
答案 1 :(得分:1)
使用现代的 java.time 类。切勿使用Date
/ Calendar
。
2020年2月29日将在第二天返回我:2019年3月1日
LocalDate // Represent a date-only value, without time-of-day and without time zone.
.of( 2020 , Month.FEBRUARY , 29 ) // Specify a date. Here, Leap Day of 2020. Returns a `LocalDate` object.
.minusYears( 1 ) // Intelligently move backwards in time one year. Returns another `LocalDate` object, per immutable objects pattern.
.toString() // Generate text representing the value of this date, in standard ISO 8601 format of YYYY-MM-DD.
2019-02-28
您使用的是可怕的日期时间类,这些类现在已经被遗留了,完全被 java.time 类所取代。
LocalDate
LocalDate
类表示没有日期,没有time zone或offset-from-UTC的仅日期值。
时区对于确定日期至关重要。在任何给定时刻,日期都会在全球范围内变化。例如,Paris France午夜之后的几分钟是新的一天,而Montréal Québec仍然是“昨天”。
如果未指定时区,则JVM隐式应用其当前的默认时区。该默认值可能在运行时(!)期间change at any moment,因此您的结果可能会有所不同。最好将您的期望/期望时区明确指定为参数。
以Continent/Region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用2-4个字母的缩写,例如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
如果要使用JVM的当前默认时区,请提出要求并作为参数传递。如果省略,代码将变得难以理解,因为我们不确定您是否打算使用默认值,还是像许多程序员一样不知道该问题。
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
或指定日期。您可以用数字设置月份,一月至十二月的理智编号为1-12。
LocalDate ld = LocalDate.of( 2020 , 2 , 29 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
或者更好的是,使用预定义的Month
枚举对象,每年的每个月使用一个。提示:在整个代码库中使用这些Month
对象,而不是仅使用整数,可以使您的代码更具自记录性,确保有效值并提供type-safety。 Year
和YearMonth
的同上。
LocalDate ld = LocalDate.of( 2020 , Month.FEBRUARY , 29 ) ;
您可以使用* java.time以几种方式进行日期时间数学运算。一种方法是调用plus
或minus
并传递Period
或Duration
。另一种方法是调用便捷方法,例如plusYears
或minusYears
。
LocalDate
类似乎只给出了您想要的使用这些方法的行为。
要明确:
请参见下面的示例run live at IdeOne.com。
让我们从29日的Day日开始,然后添加一年并减去一年。我们希望两者都能看到28号。
LocalDate leapDay2020 = LocalDate.of( 2020 , Month.FEBRUARY , 29 );
LocalDate yearBeforeLeap = leapDay2020.minusYears( 1 );
LocalDate yearAfterLeap = leapDay2020.plusYears( 1 );
System.out.println( "leapDay2020.toString(): " + leapDay2020 );
System.out.println( "yearBeforeLeap.toString(): " + yearBeforeLeap );
System.out.println( "yearAfterLeap.toString(): " + yearAfterLeap );
实际上就是我们得到的。
leapDay2020.toString():2020-02-29
yearBeforeLeap.toString():2019-02-28
yearAfterLeap.toString():2021-02-28
现在让我们从2月28日的非-年开始,然后加减一年。我们希望在这三者中都排在28位。 2020年Le年的第29个被忽略。
LocalDate nonLeap2019 = LocalDate.of( 2019 , Month.FEBRUARY , 28 );
LocalDate yearBeforeNonLeapIntoNonLeap = nonLeap2019.minusYears( 1 );
LocalDate yearBeforeNonLeapIntoLeap = nonLeap2019.plusYears( 1 );
System.out.println( "nonLeap2019.toString(): " + nonLeap2019 );
System.out.println( "yearBeforeNonLeapIntoNonLeap.toString(): " + yearBeforeNonLeapIntoNonLeap );
System.out.println( "yearBeforeNonLeapIntoLeap.toString(): " + yearBeforeNonLeapIntoLeap );
nonLeap2019.toString():2019-02-28
yearBeforeNonLeapIntoNonLeap.toString():2018-02-28
yearBeforeNonLeapIntoLeap.toString():2020-02-28
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。
答案 2 :(得分:0)
您还可以根据年份减去日期来检查年份是否为leap年
public static boolean isLeapYear(int year) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;
}
答案 3 :(得分:0)
我看不到java.util.Calendar有任何问题。在JDK 1.8中,该Java类得到了重大改进。因此,以下示例代码可以正常工作:
SimpleDateFormat sf = new SimpleDateFormat("dd MMM yyyy");
Date date=sf.parse("29 Feb 2020");
System.out.println("date="+date);
Calendar calendar=Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.YEAR, -1);
System.out.println("date="+calendar.getTime());
calendar.add(Calendar.YEAR, 1);
System.out.println("date="+calendar.getTime());
它给出的结果与Basil Bourque希望得到的结果相同:
date=Sat Feb 29 00:00:00 CET 2020
date=Thu Feb 28 00:00:00 CET 2019
date=Fri Feb 28 00:00:00 CET 2020
基本上,Java类现在使用与新类相同的ZoneInfo等。