These are the release notes and advice for upgrading Joda-Time from version 1.6 to version 2.0.
Joda-Time version 2.0 --------------------- Joda-Time is a date and time handling library that seeks to replace the JDK Date and Calendar classes. This is the eighth release of Joda-Time. This release contains enhancements, bug fixes and a time zone update. We require JDK 1.5 or later as features such as generics are used. It may be possible to use retroweaver to compile this under an earlier JDK but we haven't tried. ****************************************************************************** Compatibility The change in major version indicates compatibility issues. Please read the detailed notes below. If your code just _used_ Joda-Time and had no deprecation warnings then you will _probably_ see no issues. ****************************************************************************** Joda-Time is licensed under the business-friendly Apache License Version 2. This is the same license as all of Apache, plus other open source projects such as Spring. The intent is to make the code available to the Java community with the minimum of restrictions. If the license causes you problems please contact the mailing list. ** Please also check out our related projects ** ** https://www.joda.org/joda-time/related.html ** Enhancements since 1.6 ---------------------- - Move to Java 5, with generics See compatability notes. - Appropriate Java Memory Model settings The fields in the Base* classes, such as BaseDateTime and BaseDuration have been made volatile/final. This was necessary to comply with the Java Memory Model to ensure correct immutable behaviour. There should be no adverse effect from this change. - Add YearMonth, useful for credit card dates  - Add MonthDay, useful for birth dates without year - System clock can now be controlled by applications DateTimeUtils.MillisProvider is now public - Word based period formatters available in multiple languages  PeriodFormat provides a resource bundle based language formatter Currently supported (via online translators) are English, German, Dutch, French, Spanish and Portuguese. Corrections and additional languages welcome. - Static now() methods available on all major types  These should be used instead of the constructors when creating the current date/time Unlike the constructors, these methods validate any argument to ensure it is non-null - Static parse() methods available on all major types These allow the formatter to be controlled They do not always parse the same formats as the constructor taking an object - Parsing of month and day without year now handles February 29th This is achieved by changing the default year from 1970 to 2000 when parsing a month or day without a year. This behaviour can be controlled using the new withDefaultYear() setting on the formatter (set to 1970 for the old behaviour). - Add static factory method millis() to Duration  This checks for and returns the singleton value for ZERO - Add methods to Duration to get standard minutes, hours and days  - Support pluggable locale text and additional locales in JDK 6  Extra info accessed by reflection if JDK 6 used - Better error messages for invalid time zone ids  - Allow 'Z' and 'ZZ' in format patterns to parse 'Z' as '+00:00'  - Support parsing of date-time zone IDs like Europe/London - Support parsing of date-time zone names like "EST" and "British Summer Time" These names are not unique, so the new API methods on the builder require you to pass in a map listing all the names you want to be able to parse. The existing method is unaltered and does not permit parsing. - Add DateTimeFormatter.withZoneUTC() Provides easy way to set UTC, which is often required for parsing - Add DateTimeFormatter.parseLocalDate(), .parseLocalTime(), .parseLocalDateTime() These parse the input string in the expected manner handing time zones and offsets. For example, the LocalDate parse will parse any time or offset from the string, but will completely ignore them when returning the actual LocalDate. - Add DateTime.withEarlierOffsetAtOverlap() .withLaterOffsetAtOverlap()  Allow fine grained control of the offset during a DST overlap - Add DateTime.withTimeAtStartOfDay()  Provide a simple, reliable way to get the start of day from DateTime. - Add LocalDate.toDate()  - Add LocalDateTime.toDate() This provides a direct conversion to JDK Date which handles DST and time zone data differences - Cache hash code in LocalDate Enhances performance - DateTime constructors without seconds/millis  - DateTimeFormatter convenience methods taking an Appendable  - Add @FromString/@ToString annotations from joda-convert This does NOT require the inclusion of joda-convert at runtime! - Reduce logging from ZoneInfoCompiler by adding a verbose flag - Better Javadoc of DateTimeZone.default behaviour Compatibility with 1.6 ---------------------- Binary compatible - Not fully, see below: Source compatible - Not fully, see below: Where possible, changes are binary compatible and source compatible. The primary binary incompatible changes are the removal of the deprecated methods and the addition of Comparable to ReadablePartial. Testing has included clirr, javap and manual testing of old files with new code. Deprecated methods removed: - Chronology.getISO() - Chronology.getISOUTC() - Chronology.getISO(DateTimeZone) - Chronology.getGJ() - Chronology.getGJUTC() - Chronology.getGJ(DateTimeZone) - Chronology.getGregorian() - Chronology.getGregorianUTC() - Chronology.getGregorian(DateTimeZone) - Chronology.getJulian() - Chronology.getJulianUTC() - Chronology.getJulian(DateTimeZone) - Chronology.getBuddhist() - Chronology.getBuddhistUTC() - Chronology.getBuddhist(DateTimeZone) - Chronology.getCoptic() - Chronology.getCopticUTC() - Chronology.getCoptic(DateTimeZone) ReadablePartial has had the Comparable interface added (was previously just Javadoc). Any implementation that extended AbstractPartial should have no problems, however any implementation that extended ReadablePartial directly without implementing Comparable will be incompatible. Any direct implementations of ReadableInstant or ReadableDuration are not source compatible. This is because of the additional generics in Comparable. Your code will be source compatible if you extended AbstractInstant or AbstractDuration. This minor source incompatibility for a very few users was deemed to be the best balance of the various difficult options that generics offers. As mentioned above, erasure ensures that this source incompatibility is *not* a binary compatibility. Note that not all deprecated elements have been removed. Some methods and classes have been retained simply because the potential pain of binary incompatability is greater than the gain of removing the deprecations. Serialization compatible - Yes Data compatible - Yes, except - DateTimeZone data updated to version 2011h Semantic compatible - Yes, except Previously, DateTimeZone.forID matched time zone names case-insensitively, now it is case-sensitive Previously, parsing a string where only the month and/or day is present would use 1970 as the base year. This failed to handle February 29th. The new behaviour is as follows: If the parse includes a field with a duration between months and days inclusive and does not include any field larger than months, then the default year is changed to the value of getDefaultYear() on DateTimeFormatter, which is the year 2000 by default. In effect, this means that a pattern "ddMMM" which would previously have parsed to dates in 1970 will now parse to dates in 2000 unless further customised. The old behaviour can be simulated by calling withDefautYear(1970) on the formatter. Previously, calling various methods during a daylight savings overlap would change the offset. Now, most methods (such as withMillis/withSeconds/withMinutes/...) will retain the offset wherever possible. Previously, calling DateTimeZone.getOffsetFromLocal during a daylight savings overlap chose the earlier instant in the Western hemisphere and the later instant in the Eastern hemisphere. Now, it always returns the earlier instant (summer time) during an overlap. This affects the constructor of DateTime and other methods. Previously, DateTimeZone.getMillisKeepLocal used DateTimeZone.getOffsetFromLocal, now it uses DateTimeZone.convertUTCToLocal and DateTimeZone.convertLocalToUTC retaining the offset where possible Previously, the internals of DateTimeParserBucket linked the parsed offset and zone. This has now changed so that they are independent to allow the parsing of time-zone IDs. If you implemented the DateTimeParser interface (unlikely), you should re-test your logic. Previously, some parses of mixed weekyear and month formats would yield a result about a year out Now, most (but not all) of these give a more appropriate result Previously, java.util.TimeZone "MET" was incorrectly mapped to "Asia/Tehran". It is now mapped to "CET" (Central European Time). Previously, java.util.TimeZone "EET", "WET", "ECT" were mapped to European cities. They are now mapped to "EET", "WET" and "CET" respectively. Previously, java.util.TimeZone "IET", "AGT", "IST" and "VST" were mapped to old time-zone IDs. They are now mapped to the newer IDs "America/Indiana/Indianapolis", "America/Argentina/Buenos_Aires", "Asia/Kolkata" and "Asia/Ho_Chi_Minh". Deprecations since 1.6 ---------------------- - DateTimeFormatter.getChronolgy()  Incorrect spelling - new method DateTimeFormatter.getChronology() Bug fixes since 1.6 ------------------- - LocalTime.fromDateFields() Now handles times based on java.util.Date before 1970 - LocalDate.toInterval()  Now handles time zones which have no midnight at DST cutover - DateTimeZone.convertLocalToUTC [3102760,2182444,2553453] New method now retains the offset wherever possible during calculations This affects higher methods like withHourOfDay/withMinuteOfHour/withSecondOfMinute/withMillisOfSecond which now do not change offset when called within a DST overlap - DateTimeZone.convertLocalToUTC  Now handles date after last ever DST change - DateTimeZone.getOffsetFromLocal  The behaviour during DST overlaps is now defined to always return the earlier instant which is normally known as daylight or summer time. Previously, the result varied by hemisphere This affects the constructor of DateTime and other methods - DateTimeZone.getMillisKeepLocal The behaviour now retains the offset when changing zones where possible This affects DateTime.withZoneRetainFields and MutableDateTime.setZoneRetainFields - DateTimeZone.getDefault [3048468,3056104] Handle missing user.timezone system property on Android that resulted in stack overflow - DateTimeZone.forTimeZone  Time-zone ID "MET" from java.util.TimeZone is now mapped correctly. See compatibility notes above. - Duration.toString Fixed to work correctly for negative values - Duraton.toPeriod(), new Period(long), new MutablePeriod(long)  Fixed to obey Javadoc. Previously, they didn't obey the Javadoc if the default time-zone had no daylight savings. - Period formatting concurrency  Fix possible concurrency hole in PeriodFormatBuilder.Separator - Period formatter builder append(PeriodFormatter) did not handle some case  If the appended formatter contained a separator as the first element, it failed - Classloading CachedDateTimeZone could invalidate state  Default time zone now lazily loaded - DateTimeUtils shared static variable now volatile  - DateTimeZone.forID(String) now case-sensitive Previously, it was case-insensitive - Handle broken serialization in other tools  Some tools can't handle the joda-time stub serialization, kludge a fix for them - Standard DateTimeFieldType implements hashCode and equals for stability across serialization - Conversion from parsed values to a date-time handles weird sets of fields better  This change is mostly for combinations like weekyear-month-week The new code doesn't handle all combinations perfectly, but its better than it was - Time zone compiler now handles 24:00  - Time zone compiler now handles non-UTC better - Remove OSGi BundleExecutionEnvironment [3175068,3175612] - Javadoc fix in Months  - Javadoc fix in PeriodFormatterBuilder