我目前正在与Java.Util.Calendar
挣扎
我有一个方法创建一个日历,其中包含年,月和日的随机值。
public Calendar getRandomGeburtstag() {
int year = 1999 - (int) (Math.random() * 80);
int month = (int) (Math.random() * 12) + 1;
int monthLength = 28;
int day = (int) (Math.random() * monthLength) + 1;
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(year, month, day);
return calendar;
}
我将此日历存储在" Person" class,有一个简单的getter方法。
然后我在两个不同的场合请求日历。
在此期间,该对象未被改变。
打印日历会产生两种不同的输出:
java.util.GregorianCalendar[areAllFieldsSet=false,ERA=?,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=?,HOUR=?,HOUR_OF_DAY=?,MINUTE=?,SECOND=?,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]
和
java.util.GregorianCalendar[areAllFieldsSet=true,ERA=1,WEEK_OF_YEAR=52,WEEK_OF_MONTH=5,DAY_OF_YEAR=362,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=4,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=3600000,DST_OFFSET=0]
(我省略了保持相同的字段,它们都在两个打印输出中设置)
如您所见,以前未设置的所有字段在两个请求之间的某处都有默认值或计算值。
请求之间没有使用对象,因此它可能是JVM
问题是,字段ZONE_OFFSET
由我无法访问的方法使用。仅在给出ZONE_OFFSET=?
时才打印所需的输出
有什么办法可以阻止自动分配这些值吗?
答案 0 :(得分:2)
这可能不是您正在寻找的答案,但使用java.time
包编写会更容易
public LocalDate getRandomGeburtstag() {
LocalDate min = LocalDate.of(1919, 1, 1);
LocalDate max = LocalDate.of(1999, 12, 31);
long diff = max.toEpochDay() - min.toEpochDay();
return LocalDate.ofEpochDay(min.toEpochDay() + (long) (Math.random() * diff));
}
您当前的方法不会产生所有可能的日子,例如29,30,31。我认为这是一种解决方法,但是当您使用epoch millis时不需要它。
答案 1 :(得分:1)
也许您可以在这些答案中找到有关Calendar
奇怪行为的更多信息:
基本上,当您调用set
时,不会自动重新计算所有这些内部字段,并且内部重新计算是任意的,您无法完全控制何时完成以及重新计算哪些字段。
最好的替代方法是使用注释中建议的ThreeTen Backport,这样您就可以使用LocalDate
以及java.time API的所有其他功能 - 这些功能没有Calendar
{1}}。
但是如果你坚持使用旧的API,那么就有一个(丑陋的)替代方案:
SimpleDateFormat sdf = new SimpleDateFormat("d-M-yyyy");
Date date = sdf.parse(day + "-" + month + "-" + year);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
Date
将时间字段设置为零,Calendar
将设置所有字段(打印时无?
)。
只需提醒上面的月份值是1到12,而在calendar.set
方法中,接受的值是0到11(这个可怕的API的另一个恼人的行为)。