如何修复GregorianCalendar中的gc.setTime()

时间:2017-10-24 12:10:00

标签: java date gregorian-calendar

以下是我的代码中的一部分:

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(dateFormat.parse(jahr+"-"+monat+"-"+tag));

现在我想在德国打印一些复活节假期。

gc.add(Calendar.DAY_OF_MONTH, -2);
System.out.println("Karfreitag;"+dateFormat.format(gc.getTime()));
gc.add(Calendar.DAY_OF_MONTH, +3);
System.out.println("Ostermontag;"+dateFormat.format(gc.getTime()));
gc.add(Calendar.DAY_OF_MONTH, +38);

使它更清晰一点。 Eastersunday于今年16.04.2017举行。

所以第一次打印出来的工作正常,'Karfreitag'是在eastersunday前两天。所以这是14.04.2017。

继续前往Eastermonday会引发一个问题。 Eastermonday是eastersunday之后的第二天。不幸的是,我必须增加+3天,因为我用'Karfreitag'日期覆盖了eastersunday日期。

所以我想知道是否有可能从eastersunday修复日期,以便我必须将我的第3行更改为:

gc.add(Calendar.DAY_OF_MONTH, +1);

它认为这可能很容易,但我不知道如何以适当的方式改变这一点。

3 个答案:

答案 0 :(得分:4)

add方法更改当前日历实例时,一种解决方案是使用clone()方法创建另一个:

// clone it before changing it
GregorianCalendar other = (GregorianCalendar) gc.clone();

gc.add(Calendar.DAY_OF_MONTH, -2);
System.out.println("Karfreitag;" + dateFormat.format(gc.getTime()));

other.add(Calendar.DAY_OF_MONTH, 1);
System.out.println("Ostermontag;" + dateFormat.format(other.getTime()));

Java新日期/时间API

旧类(DateCalendarSimpleDateFormat)有lots of problemsdesign issues,它们将被新API取代。< / p>

如果您使用的是 Java 8 ,请考虑使用new java.time API。它更容易,less bugged and less error-prone than the old APIs

如果您使用的是 Java 6或7 ,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。对于 Android ,您还需要ThreeTenABP(更多关于如何使用它here)。

以下代码适用于两者。 唯一的区别是包名称(在Java 8中为java.time,在ThreeTen Backport(或Android的ThreeTenABP)中为org.threeten.bp),但类和方法名称是相同的

当您处理日期(日/月/年)时,您可以使用LocalDate课程。在这个新的API中,类是不可变的,因此添加若干天的方法总是会创建另一个对象:

LocalDate easter = LocalDate.parse("2017-04-16");

// minusDays and plusDays return a new LocalDate, keeping the original unchanged
System.out.println("Karfreitag;" + easter.minusDays(2));
System.out.println("Ostermontag;" + easter.plusDays(1));

输出将是:

  

Karfreitag; 2017年4月14日
  Ostermontag; 2017年4月17日

如果您将日,月和年的值设为int,则可以使用LocalDate方法创建of

int tag = 16;
int monat = 4;
int jahr = 2017;
// Easter
LocalDate easter = LocalDate.of(jahr, monat, tag);

从/转换为GregorianCalendar

如果您仍需要使用GregorianCalendar,则可以轻松地将其从/转换为新API。在Java 8中有新的方法来进行转换,而在Java 6/7 ThreeTen Backport中有org.threeten.bp.DateTimeUtils类:

// Java 8: convert calendar to local date
LocalDate dt = gc.toZonedDateTime().toLocalDate();

// Java 7: convert calendar to local date
LocalDate dt = DateTimeUtils.toZonedDateTime(gc).toLocalDate();

LocalDate转换回GregorianCalendar有点棘手。 LocalDate只有日期字段(日,月和年),而GregorianCalendar代表“完整日期”:特定时区的日期和时间。

因此,在将LocalDate转换为GregorianCalendar时,您必须对时间(小时,分钟等)和时区做出一些假设。一个示例是将时间设置为午夜,并使用JVM默认时区:

// Java 8: convert local date to calendar (midnight in JVM default timezone)
GregorianCalendar cal = GregorianCalendar.from(dt.atStartOfDay(ZoneId.systemDefault()));

// Java 7: convert local date to calendar (midnight in JVM default timezone)
GregorianCalendar cal = DateTimeUtils.toGregorianCalendar(dt.atStartOfDay(ZoneId.systemDefault()));

您还可以转换为当天的任何其他时间,并将时区更改为您想要的任何内容:

// set to 10:30 AM in Berlin timezone
dt.atTime(10, 30).atZone(ZoneId.of("Europe/Berlin"));

或者您可以直接使用ZonedDateTime返回的toZonedDateTime(),并在打印时提取LocalDate部分:

// convert calendar to ZonedDateTime
ZonedDateTime z = gc.toZonedDateTime();

// print just the LocalDate part
System.out.println("Karfreitag;" + z.minusDays(2).toLocalDate());
System.out.println("Ostermontag;" + z.plusDays(1).toLocalDate());

// get the original calendar back
GregorianCalendar cal = GregorianCalendar.from(z);

这个新API有lots of new types,可让您为每种情况选择最佳。

答案 1 :(得分:4)

开始使用java.time.LocalDate。它提供了一个返回实例副本的LocalDate.plusDays(long)

  

返回此LocalDate的副本,并添加指定的天数。

像这样:

LocalDate tomorrow = LocalDate.now().plusDays(1);

您可以使用LocalDate.of(int, int, int)获取实例,例如:

LocalDate date = LocalDate.of(year, month, day);

注意:这是Hugo's answer的缩短版本,只是意识到他的答案中有一部分......

答案 2 :(得分:2)

您可以像这样使用DateUtils.addDays

DateUtils.addDays(gc.getDate(), -2).getTime()

它需要一个Date对象(您可以使用gc.getDate())和int天数作为参数添加并返回Date对象而不修改您的原gc

System.out.println("Karfreitag;"+dateFormat.format(DateUtils.addDays(gc.getDate(), -2).getTime()));
System.out.println("Ostermontag;"+dateFormat.format(DateUtils.addDays(gc.getDate(), 3).getTime()));
System.out.println("something else;"+dateFormat.format(DateUtils.addDays(gc.getDate(), 38).getTime()));

在Android中,它可以从API级别3获得,在Java中你必须使用Apache Commons