2

我目前正在努力解决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”类中,该类有一个简单的 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=?仅在给出时才打印所需的输出。
有什么办法可以停止这些值的自动分配?

4

2 回答 2

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 上操作时不需要它。

于 2018-03-13T09:48:26.527 回答
1

Calendar也许你可以在这些答案中找到更多关于's 怪异行为的信息:

基本上,当您调用 时,所有这些内部字段都不会自动重新计算set,并且内部重新计算是任意的,您无法控制何时完成以及重新计算哪些字段。

最好的替代方法是使用 ThreeTen Backport,正如评论中所建议的那样,这样您就可以使用LocalDatejava.time API 的所有其他功能 - 它没有这么多混乱的Calendar.

但是如果你坚持使用旧的 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 的另一个令人讨厌的行为)。

于 2018-03-13T16:14:45.697 回答