以下是我的代码中的一部分:
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);
它认为这可能很容易,但我不知道如何以适当的方式改变这一点。
答案 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()));
旧类(Date
,Calendar
和SimpleDateFormat
)有lots of problems和design 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
,则可以轻松地将其从/转换为新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