java.time
The Answer by Buurman is almost correct, but not quite.
The Joda-Time project is indeed in maintenance-mode, with its creators advising migration to the java.time classes built into Java 8 and later. Both Joda-Time and the java.time JSR 310 are led by the same man, Stephen Colebourne. So migration is fairly easy, as many of the core ideas are the same.
If you are trying to represent "lunch every Saturday at noon", you cannot reliably store exact moments going out into the future. Politicians around the world have shown a predilection for redefining their time zone(s). They do so surprisingly often, and often do so with very little warning. So you cannot know when "noon" is going to be, in terms of a time-of-day on the clock. A changing definition of the clock means you are chasing a moving target.
So, "lunch every Saturday at noon" requires tracking a day-of-week and tracking a time-of-day. Java has classes for both.
DayOfWeek dayOfWeek = DayOfWeek.SATURDAY ; // Enum with seven predefined objects, Monday-Saturday.
LocalTime localTime = LocalTime.of( 12 , 0 ) ; // Noon.
You also need to store the time zone intended when you said "noon". Every day, noon happens much earlier in India than it does in France, and happens even later in Québec. So a time-of-day only has meaning when in the context of a particular 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 zoneId = ZoneId.of( "America/Montreal" ) ;
You can project out a series of these lunches, determining the exact moment (point on the timeline) for each. But you can only do so provisionally. Given that governments have proven they are willing to redefine the offset-from-UTC of their time zone with a forewarning of only months, weeks, days, or even hours, you cannot store these projections. Calculate them dynamically at runtime.
Determine today. This requires a time zone of course. For any given moment, the date varies around the globe by zone.
LocalDate today = LocalDate.now( zoneId ) ;
Get the next Saturday, or stay with today if already a Saturday.
LocalDate firstSaturday = today.with( TemporalAdjusters.nextOrSame( dayOfWeek ) ) ;
Determine the point on the timeline for noon in that zone on that date.
ZonedDateTime firstLunch = ZonedDateTime.of( firstSaturday , localTime , zoneId ) ;
You can view that same moment as UTC by extracting an Instant
.
Instant firstLunchInstant = firstLunch.toInstant() ;
You can continue out this projection by adding a week to the LocalDate
, and repeating the steps above to ask for noon on that next date. If that time-of-day happens to not be valid on that date in that zone (such as a Daylight Saving Time "Spring-ahead" cutover), the ZonedDateTime
class adjusts accordingly. Be sure to read the doc to understand its adjustment algorithm.
int weeksToProject = 10 ; // Run out 10 weeks.
List< ZonedDateTime > lunches = new ArrayList<>( weeksToProject ) ;
LocalDate localDate = firstSaturday ;
for( int i = 0 ; i < 10 ; i ++ ) {
localDate = localDate.plusWeeks( i ) ;
ZonedDateTime zdt = ZonedDateTime.of( localDate , localTime , zoneId ) ;
lunches.add( zdt ) ;
}
Database
As for storing "lunch every Saturday at noon" in a database:
- The time-of-day can be stored in the SQL-standard type
TIME WITHOUT TIME ZONE
type.
myPreparedStatement.setObject( … , localTime ) ;
LocalTime localTime = myResultSet.getObject( … , LocalTime.class ) ;
- The day-of-week could be stored as text in a VARCHAR using the English-hardcoded
DayOfWeek
enum value names such as MONDAY
. Or you could store the day-of-week as in integer number. For a number, I strongly suggest using the ISO 8601 standard 1-7 for Monday-Sunday. Be sure to clearly document the meaning of your number for posterity.
- The time zone can be stored as text in a VARCHAR in standard IANA
Continent/Region
format.
The ZonedDateTime
objects should only be transient, created dynamically as needed in the moment. So you will not be storing them.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.