在同一天内正确验证时间间隔
Proper validation of time intervals within the same day
我有一个方法如下:
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?
}
问题:
我应该如何验证 hours/minutes?应该包括实际日期还是不相关?
我应该更新 localDate
而不是 appointmentCalendar
吗?
你在这里工作太辛苦了。
避免遗留日期时间 classes
避免使用麻烦的旧日期时间 classes,例如 Date
和 Calendar
。现在是遗留问题,被 java.time classes.
取代
不要混用日期时间库
不要混用不同的日期时间库。如果使用 Joda-Time,则不需要 java.util.Date
也不需要 java.util.Calendar
。如果使用 java.time classes,则不需要 Joda-Time 也不需要 java.util.Date
/.Calendar
.
Joda-Time project, now in maintenance mode,建议迁移到java.time。
业务规则
Should the actual date be included or is that not relevant?
我们无法告诉您是否考虑日期。这取决于您的业务规则。
例如,如果您的企业总是从中午到 13:00 午休,那么任何标有该时段时间的企业记录都必须无效。如果您每天都使用相同的午休时间,那么日期在这里是无关紧要的。
但是如果您的场景类似于记录工人的工作时间,那么任何两个时间段都不应在同一天重叠。在这种情况下,您必须考虑日期。
ZonedDateTime
Should I update the localDate instead of the appointmentCalendar?
a) 你不应该混合这些 classes,如上所述。
b) 在 Joda-Time 和 java.time 中,LocalDate
class 表示没有时间的仅日期值。和它的兄弟 Local…
classes 一样,它故意没有时区的概念。所以根本不适合你的目的。
您需要使用 ZonedDateTime
来表示在您预期的时区内有意义的日期和时间。
指定 proper time zone name in the format of continent/region
, such as 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 class 是 immutable objects。因此,您不会更改(“改变”)它们的值。相反,您根据原始值实例化一个新对象。
区间
您可能会发现 Interval
class in ThreeTen-Extras 项目在这里很有帮助。
Interval a = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );
您可以使用 contains
、overlaps
、encloses
、isBefore
和 isAfter
等方法比较区间。
Boolean overlaps = a.overlaps( b );
传递对象
传递对象而不是传递零碎数据的原始元素。
因此,不是传递月份、日期和小时的整数等基元,而是传递 java.time 对象,例如 Instant
、OffsetDateTime
、ZonedDateTime
。当您只有日期或时间时,传递 LocalDate
或 LocalTime
.
默认时区
要获取 JVM 当前的默认时区,请调用 ZoneId.systemDefault
。
但如果重要的话,您应该询问用户他们的 desired/expected 时区。该默认值可以随时通过该 JVM 中任何应用程序的任何线程中的任何代码更改 运行。
我有一个方法如下:
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?
}
问题:
我应该如何验证 hours/minutes?应该包括实际日期还是不相关?
我应该更新
localDate
而不是appointmentCalendar
吗?
你在这里工作太辛苦了。
避免遗留日期时间 classes
避免使用麻烦的旧日期时间 classes,例如 Date
和 Calendar
。现在是遗留问题,被 java.time classes.
不要混用日期时间库
不要混用不同的日期时间库。如果使用 Joda-Time,则不需要 java.util.Date
也不需要 java.util.Calendar
。如果使用 java.time classes,则不需要 Joda-Time 也不需要 java.util.Date
/.Calendar
.
Joda-Time project, now in maintenance mode,建议迁移到java.time。
业务规则
Should the actual date be included or is that not relevant?
我们无法告诉您是否考虑日期。这取决于您的业务规则。
例如,如果您的企业总是从中午到 13:00 午休,那么任何标有该时段时间的企业记录都必须无效。如果您每天都使用相同的午休时间,那么日期在这里是无关紧要的。
但是如果您的场景类似于记录工人的工作时间,那么任何两个时间段都不应在同一天重叠。在这种情况下,您必须考虑日期。
ZonedDateTime
Should I update the localDate instead of the appointmentCalendar?
a) 你不应该混合这些 classes,如上所述。
b) 在 Joda-Time 和 java.time 中,LocalDate
class 表示没有时间的仅日期值。和它的兄弟 Local…
classes 一样,它故意没有时区的概念。所以根本不适合你的目的。
您需要使用 ZonedDateTime
来表示在您预期的时区内有意义的日期和时间。
指定 proper time zone name in the format of continent/region
, such as 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 class 是 immutable objects。因此,您不会更改(“改变”)它们的值。相反,您根据原始值实例化一个新对象。
区间
您可能会发现 Interval
class in ThreeTen-Extras 项目在这里很有帮助。
Interval a = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );
您可以使用 contains
、overlaps
、encloses
、isBefore
和 isAfter
等方法比较区间。
Boolean overlaps = a.overlaps( b );
传递对象
传递对象而不是传递零碎数据的原始元素。
因此,不是传递月份、日期和小时的整数等基元,而是传递 java.time 对象,例如 Instant
、OffsetDateTime
、ZonedDateTime
。当您只有日期或时间时,传递 LocalDate
或 LocalTime
.
默认时区
要获取 JVM 当前的默认时区,请调用 ZoneId.systemDefault
。
但如果重要的话,您应该询问用户他们的 desired/expected 时区。该默认值可以随时通过该 JVM 中任何应用程序的任何线程中的任何代码更改 运行。