任意分配Java.Util.Calendar值

时间:2018-03-13 09:32:59

标签: java java-7 java.util.calendar

我目前正在与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=?时才打印所需的输出 有什么办法可以阻止自动分配这些值吗?

2 个答案:

答案 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的另一个恼人的行为)。