I have a method as follows:
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?
}
Questions:
How should I validate the hours/minutes? Should the actual date be included or is that not relevant?
Should I update the localDate
instead of the appointmentCalendar
?
You are working much too hard here.
Avoid using the troublesome old date-time classes, such as Date
& Calendar
. Now legacy, supplanted by the java.time classes.
Do not mix the different date-time libraries. If using Joda-Time, no need for java.util.Date
and no need for java.util.Calendar
. And if using java.time classes, no need for Joda-Time and no need for java.util.Date
/.Calendar
.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
Should the actual date be included or is that not relevant?
We cannot tell you whether to consider the date or not. That depends on your business rules.
For example, if your business always takes a lunch break from noon to 13:00, then any business record marked with a time-of-day in that hour must be invalid. Date is irrelevant here if you always take the same lunch break every single day.
But if your scenario is something like recording a worker’s periods worked, then no two periods should overlap on the same day. In this case you must consider the date.
ZonedDateTime
Should I update the localDate instead of the appointmentCalendar?
a) You should not be mixing these classes, as discussed above.
b) In both Joda-Time and java.time, the LocalDate
class represents a date-only value without time-of-day. And like its sibling Local…
classes, it purposely has no concept of time zone. So not at all a fit for your purpose.
You need to use ZonedDateTime
to represent a date and a time-of-day that has meaning within your intended time zone.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
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 );
To get the current moment:
Instant instant = Instant.now(); // UTC.
ZonedDateTime zdt = instant.atZone( z );
…or, as a shortcut…
ZonedDateTime zdt = ZonedDateTime.now( z );
Also, the java.time classes are immutable objects. So you do not change (“mutate”) their values. Instead you instantiate a new object based on the original’s values.
You may find the Interval
class in ThreeTen-Extras project to be helpful here.
Interval a = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );
You can compare intervals with methods such as contains
, overlaps
, encloses
, isBefore
, and isAfter
.
Boolean overlaps = a.overlaps( b );
Rather than pass around mere primitives of piecemeal data, pass objects.
So instead of passing primitives such as integers for month, date, and hour, pass java.time objects such as Instant
, OffsetDateTime
, ZonedDateTime
. When you have only the date or only the time-of-day, pass LocalDate
or LocalTime
.
To get the JVM’s current default time zone, call ZoneId.systemDefault
.
But if important you should be asking the user for their desired/expected time zone. That default can change at any moment by any code in any thread of any app running in that JVM.