我有一个方法如下:
public void storeAppointment(int year,
int monthOfYear,
int dayOfMonth,
int hourOfDayFrom,
int minuteFrom,
int hourOfDayUntil, int minuteUntil) {
Calendar appointmentCalendar = Calendar.getInstance();
appointmentCalendar.set(year, monthOfYear, dayOfMonth);
TimeZone tz = appointmentCalendar.getTimeZone();
DateTimeZone jodaTz = DateTimeZone.forID(tz.getID());
DateTime appointmentDateTime = new DateTime(appointmentCalendar.getTimeInMillis(), jodaTz);
LocalDate localDate = appointmentDateTime.toLocalDate();
// At this point I have the appointment date.
// Should e.g. throw an exception for invalid time interval
validate(hourOfDayFrom, minuteFrom, hourOfDayUntil, minuteUntil);
// set proper times for calendar
appointmentCalendar.set(Calendar.HOUR, hourOfDay);
appointmentCalendar.set(Calendar.MINUTE, minute);
// store date and times
// Should I update the localDate instead of the appointmentCalendar?
}
问题:
我应该如何验证小时/分钟?是否应包括实际日期或不相关?
我应该更新localDate
而不是appointmentCalendar
吗?
答案 0 :(得分:2)
你在这里工作太辛苦了。
避免使用麻烦的旧日期时间类,例如Date
& Calendar
。现在是遗留的,取而代之的是java.time类。
不要混用不同的日期时间库。如果使用Joda-Time,则无需java.util.Date
,也不需要java.util.Calendar
。如果使用java.time类,则不需要Joda-Time,也不需要java.util.Date
/ .Calendar
。
现在位于Joda-Time的maintenance mode项目建议迁移到java.time。
是否应包括实际日期或不相关?
我们无法告诉您是否考虑日期。这取决于您的业务规则。
例如,如果您的公司总是从中午到13:00休息,那么在该小时标记有时间的任何商业记录都必须无效。如果你每天都在同一个午休时间,这里的日期无关紧要。
但是,如果您的方案类似于记录工作人员的工作时间,那么在同一天不会有两个时间段重叠。在这种情况下,您必须考虑日期。
ZonedDateTime
我应该更新localDate而不是appointmentCalendar吗?
a)如上所述,你不应该混合这些类。
b)在Joda-Time和java.time中,LocalDate
类表示没有时间的仅日期值。和它的兄弟Local…
类一样,它故意没有时区概念。所以根本不适合你的目的。
您需要使用ZonedDateTime
来表示在预期时区内有意义的日期和时间。
以continent/region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate ld = LocalDate.of( 2016 , 1 , 23 );
LocalTime lt = LocalTime.of( 12 , 30 );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
获取当前时刻:
Instant instant = Instant.now(); // UTC.
ZonedDateTime zdt = instant.atZone( z );
......或者,作为捷径......
ZonedDateTime zdt = ZonedDateTime.now( z );
此外,java.time类为immutable objects。所以你不要改变(“改变”)他们的价值观。而是根据原始值实例化一个新对象。
您可以在Interval
项目中找到ThreeTen-Extras课程,以便在此处提供帮助。
Interval a = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );
您可以将时间间隔与contains
,overlaps
,encloses
,isBefore
和isAfter
等方法进行比较。
Boolean overlaps = a.overlaps( b );
不是传递零碎数据的基元,而是传递对象。
因此,不要传递月份,日期和小时等整数等基元,而是传递Instant
,OffsetDateTime
,ZonedDateTime
等java.time对象。如果您只有日期或只有时间,请通过LocalDate
或LocalTime
。
要获取JVM的当前默认时区,请致电ZoneId.systemDefault
。
但是如果重要的话,你应该问用户他们想要的/预期的时区。该默认值可随时由该JVM中运行的任何应用程序的任何线程中的任何代码更改。