Some common questions about Joda-Time are answered here.
Joda-Time only allows the key classes to store valid date-times. For example, 31st February is not a valid date so it can't be stored (except in Partial).
The same principle of valid date-times applies to daylight savings time (DST). In many places DST is used, where the local clock moves forward by an hour in spring and back by an hour in autumn/fall. This means that in spring, there is a "gap" where a local time does not exist.
The error "Illegal instant due to time zone offset transition" refers to this gap. It means that your application tried to create a date-time inside the gap - a time that did not exist. Since Joda-Time objects must be valid, this is not allowed.
Possible solutions may be as follows:
Use LocalDateTime, as all local date-times are valid.
When converting a LocalDate to a DateTime, then use toDateTimeAsStartOfDay()
as this handles and manages any gaps.
When parsing, use parseLocalDateTime() if the string being parsed has no time-zone.
Not all cases of this error have a simple solution. Hopefully this FAQ has explained what the error means allowing you to work out what the correct solution will be.
Joda-Time releases only occur infrequently. But time-zone changes happen all the time. As such, it may well be that the rules are out of date.
Between the Joda-Time releases, it is your responsibility to update the jar file with the latest time-zone rules. You must update both the JDK and Joda-Time rules to the same version at the same time to avoid problems. See the update time-zone rules guide for more details.
The time zone rules occur in three key places, your operating system, the JDK and Joda-Time. To be sure of hitting no issues, you should ensure that all three of these have been updated.
Version 1.5 of Joda-Time contains all the daylight savings rule updates for the 2007 US change. For earlier versions of Joda-Time the situation is more complex:
If your application only uses the major time zones of the US, then you need Joda-Time 1.2 or later. If your application also uses the major time zones of the Canada, then you need Joda-Time 1.2.1 or later. If your application uses the minor time zones of the US or Canada, then you need Joda-Time 1.4 or later. For Bermuda (Atlantic/Bermuda) you need Joda-Time 1.4 or later. For the Bahamas (America/Nassau) you need Joda-Time 1.5.
For any future, or similar time zone change, you can upgrade your Joda-Time jar by following these instructions.
There are two main reasons for this.
The first reason is that both the JDK and Joda-Time have time-zone data files. It is important to keep both up to date and in sync if you want to compare the offset between the two.
The second reason affects date-times before the modern time-zone system was introduced. The time-zone data is obtained from the time-zone database. The database contains information on "Local Mean Time" (LMT) which is the local time that would have been observed at the location following the Sun's movements.
Joda-Time uses the LMT information for all times prior to the first time-zone offset being chosen in a location. By contrast, the JDK ignores the LMT information. As such, the time-zone offset returned by the JDK and Joda-Time are different for date-times before the modern time-zone system.
This question has more than one answer! If you just want the number of whole days between two dates, then you can use the new Days class in version 1.4 of Joda-Time.
Days d = Days.daysBetween(startDate, endDate); int days = d.getDays();
If however you want to calculate the number of days, weeks, months and years between the two dates, then you need a Period By default, this will split the difference between the two datetimes into parts, such as "1 month, 2 weeks, 4 days and 7 hours".
Period p = new Period(startDate, endDate);
Period p = new Period(startDate, endDate, PeriodType.yearMonthDay());
For more info, consult the period guide.
Historically, every country has found their own solution to measuring time. This has often been political and religious. To simplify the problem, especially in the realm of computer data transfer, the ISO-8601 standard was founded.
The ISO standard defines a framework for passing dates and times between computer systems in a standard way. The standard uses the proleptic Gregorian calendar. This makes it fully compatible with the calendar system used in most of the world after 1582. The standard warns that it may only be used to represent dates before 1582 'by mutual agreement'.
The standard defines twelve months January to December numbered 1 to 12 and seven days Monday to Sunday, numbered 1 to 7. In addition it defines the first week of the year as the first week to have most of its days in the new year. This can result in the first week of a year starting in the previous year and the last week ending in the following year.
The key point about ISO-8601 is that it is a framework for dates not an absolute single definition. The most common form is YYYY-MM-DDTHH:MM:SS.SSSZ, in other words year-month-day letter 'T' hour:minute:second and fractions.
Dates and times can be a localization nightmare (or should that be localisation...). Often political, geographic and religious factors have come into play. We wanted to avoid these factors if possible.
The ISO8601 standard is a good choice because it is a standard designed for computer data transfer and developed by a standards body. It is also a good choice because it is compatible with the calendar system used by most businesses worldwide today. Finally, it is a good choice as it forces API users to think about the decision they make if they require non-ISO or historically accurate calendar systems.
The main time interface is ReadableInstant. All classes that implement this interface, such as DateTime, store time as a single long value representing milliseconds. The epoch of the definition is 1970-01-01T00:00:00Z, which is the same as the JDK time definition and usage. Querying a field, such as year or hour, will calculate the value from the millisecond instant.
A secondary time interface is ReadablePartial. Classes implementing this interface store data in two ways. The 'local' classes, such as LocalDate and LocalTime store the number of milliseconds from 1970 without a time zone. All other implementations, such as YearMonthDay and TimeOfDay, store time as a one int value for each field.
There are three main reasons for using a single long value to store the time.
The range supported is -292,269,054 to 292,277,023. In other words, roughly +/- 290 million years to millisecond precision.
If you want a date outside this range, ask yourself if you really want millisecond precision. In reality, dates this far in the past or future should only be stored as years - anything else is meaningless.
Joda-Time does not support accuracy of times below millisecond. Physics defines time scales down to 5E-44 secs. The only way to accurately record these sorts of times is using the BigInteger class. This would severely compromise the performance of the whole API for a very limited use.
Joda-Time is designed for performance. Compared to java.util.Calendar, java.text.SimpleDateFormat, and java.util.TimeZone, nearly all equivalent operations in Joda-Time are faster. The significant exceptions are operations to get or set an individual field.
Calling "get" on java.util.Calendar is very fast because it doesn't do any work. Calendar calculates all fields in advance, even if many of those fields you won't need. Calendar's set method is fast because it defers calculations until later. Calling Calendar.get after calling Calendar.set forces all the field values to be re-calculated. Calling Joda's DateTime.get method after calling DateTime.set only performs the minimum amount of calculations, and the pair is faster than Calendar.
Joda-Time also allocates very few temporary objects during operations, and performs almost no thread synchronization. In systems that are heavily multi-threaded or use a lot of memory, Calendar, SimpleDateFormat, and TimeZone can become bottlenecks. When the Joda-Time classes are used instead, the bottlenecks go away.
Every public class in Joda-Time is documented as being thread-safe or not. Joda-Time makes heavy use of the immutability design pattern, and all immutable classes in Joda-Time are thread-safe. Many mutable classes whose instances are not likely to be shared are not thread-safe, and are documented as such.
The most common multi-threading mistake made by Java programmers is in the use of SimpleDateFormat. Calling its format method on a shared instance by concurrent threads can produce bizarre results. All of Joda-Time's formatting classes are thread-safe and immutable.
Joda-Time does not support leap seconds. Leap seconds can be supported by writing a new, specialized chronology, or by making a few enhancements to the existing ZonedChronology class. In either case, future versions of Joda-Time will not enable leap seconds by default. Most applications have no need for it, and it might have additional performance costs.
No, you only need to learn a small subset of the classes in the API. The javadoc clearly indicates which packages contain user classes, and which contain implementation classes. In addition, there are a large number of package scoped classes, which are hidden in the javadoc view anyway. Most applications will not need to directly import, extend or implement classes in the implementation packages. Basically, the API consists of the main package, plus the formatting package.
The JDK TimeZone class varies in the support it can provide from one JDK release to another. The rules for determining Daylight Saving Time also change frequently. The Joda solution uses the international standard format for time zone rule data, and allows it to be updated independently of the timing of JDK releases. With perhaps 8 releases of the time zone rules per year this can be quite significant.
'Joda' is a short, four letter name, beginning with 'j' whose domain name was free. It is not an acronym.
The 'J' in 'Joda' is pronounced the same as the 'J' in 'Java'. The project is not capable of wielding a light saber and is thus pronounced differently.