<?xml version="1.0" encoding="ISO-8859-1"?>

<document>
 <properties>
  <title>Java date and time API - Upgrade from 1.6 to 2.0</title>
  <author>Stephen Colebourne</author>
 </properties>

<body>

<section name="Upgrade">
<p>
These are the release notes and advice for upgrading Joda-Time from
version 1.6 to version 2.0.
<source>
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   **
** http://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 [1863090]

- 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 [1252708]
  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 [3134566]
  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 [2648777]
  This checks for and returns the singleton value for ZERO

- Add methods to Duration to get standard minutes, hours and days [2862884]

- Support pluggable locale text and additional locales in JDK 6 [2690370]
  Extra info accessed by reflection if JDK 6 used

- Better error messages for invalid time zone ids [2781835]

- Allow 'Z' and 'ZZ' in format patterns to parse 'Z' as '+00:00' [2827359]

- 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() [3192457]
  Allow fine grained control of the offset during a DST overlap

- Add DateTime.withTimeAtStartOfDay() [3304757]
  Provide a simple, reliable way to get the start of day from DateTime.

- Add LocalDate.toDate() [2465359]
- 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 [1982629]

- DateTimeFormatter convenience methods taking an Appendable [2607923]

- 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() [2783325]
  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() [2487417]
  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 [2903029]
  Now handles date after last ever DST change

- DateTimeZone.getOffsetFromLocal [2952991]
  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 [3216471]
  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) [3264409]
  Fixed to obey Javadoc.
  Previously, they didn't obey the Javadoc if the default time-zone had no daylight savings.

- Period formatting concurrency [2820871]
  Fix possible concurrency hole in PeriodFormatBuilder.Separator

- Period formatter builder append(PeriodFormatter) did not handle some case [2495455]
  If the appended formatter contained a separator as the first element, it failed

- Classloading CachedDateTimeZone could invalidate state [2935625]
  Default time zone now lazily loaded

- DateTimeUtils shared static variable now volatile [2986043]

- DateTimeZone.forID(String) now case-sensitive
  Previously, it was case-insensitive

- Handle broken serialization in other tools [3117678]
  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 [3161586]
  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 [2804258]

- Time zone compiler now handles non-UTC better

- Remove OSGi BundleExecutionEnvironment [3175068,3175612]

- Javadoc fix in Months [2721880]

- Javadoc fix in PeriodFormatterBuilder [3100939]
</source>
</p>
</section>

</body>
</document>
