Showing posts with label jsr310. Show all posts
Showing posts with label jsr310. Show all posts

Tuesday, 7 February 2017

Java Time (JSR-310) enhancements in Java SE 9

The java.time.* API (JSR-310) was added to Java SE 8, but what has been going on since then?

Java Time in Java SE 9

There are currently 117 java time issues targetted into Java SE 9. Most of these are not especially interesting, with a lot of mistakes in the Javadoc that needed fixing. What follows are some of the interesting ones:

Main enhancements:

JDK-8146218 - Add LocalDate.datesUntil method producing Stream.
Adds two new methods - LocalDate.datesUntil(LocalDate) and LocalDate.datesUntil(LocalDate,Period) - returning a stream of dates.

JDK-8068730 - Increase precision of Clock.systemUTC().
The clock in Java - System.currentTimeMillis() - has ticked in milliseconds since Java was first released. With Java SE 9, users of Clock will see higher precision, depending on the available clock of the operating system.

JDK-8071919 - Clock.tickMillis(ZoneId zone) method.
With the system clock now returning higher precision, a new method was added - Clock.tickMillis(ZoneId) - that chops off the extra precision to restrore the millisecond ticking behaviour of Java SE 8.

JDK-8030864 - Add efficient getDateTimeMillis method to java.time.
This adds two methods named epochSecond to Chronology that have no object creation to convert date-time fields to an epoch-second.

JDK-8142936 - Duration methods for days, hours, minutes, seconds, etc.
The Java SE 8 API of Duration turned out to be incomplete for certain use cases. This change adds a slew of new methods that allow parts of the duration to be reliably returned.

JDK-8148849 - Truncating Duration.
Adds a method Duration.truncatedTo(TemporalUnit) to allow truncation, similar to the existing method on Instant.

JDK-8032510 - Add Duration.dividedBy(Duration).
A new method to allow a duration to be divided by another duration.

JDK-8133079 - LocalDate and LocalTime ofInstant() factory methods.
Add new factory methods in LocalDate and LocalTime to simplify conversion from Instant.

JDK-8143413 - Add toEpochSecond methods for efficient access.
Add methods to LocalDate, LocalTime and OffsetTime to optimize conversion to epoch-seconds.

Formatting:

JDK-8148947 - DateTimeFormatter pattern letter 'g'.
This adds a pattern letter for modified Julian days.

JDK-8155823 - Add date-time patterns 'v' and 'vvvv'.
This adds support for the "generic non-location" format for time-zones as defined by CLDR, such as "Pacific Time" (the format ignores daylight saving time). Methods were also added to the formatter builder - DateTimeFormatterBuilder.appendGenericZoneText().

JDK-8066806 - DateTimeFormatter cannot parse offset with single digit hour.
The formatter is extended to support 11 more time-zone offset formats, including single digit hours such as +2:00.

JDK-8031085 - DateTimeFormatter won't parse format "yyyyMMddHHmmssSSS".
This extends support for adjacent value parsing to fractions. Where in Java SE 8 a pattern like this looks like it should work, but doesn't, in Java SE 9 it just works.

JDK-8145633 - Adjacent value parsing for Localized Patterns .
This extends support for adjacent value parsing to localized patterns, such as week-based-year and week of year.

JDK-8148949 - DateTimeFormatter pattern letters 'A','n','N'.
These patterns were altered to be more flexible and produce less errors.

Performance:

JDK-8073394 - Clock.systemUTC() should return a constant.
This change avoids creating unecessary objects when using Clock.

JDK-8074003 - ZoneRules.getOffset(Instant) can be optimized.
This change reduces object churn when looking up time-zone data.

JDK-8074002 - ZoneId.systemDefault() should be faster.
This enhancement uses a clever approach to cache the time-zone while handling TimeZone.setDefault.

JDK-8068803 - Performance of LocalDate.plusDays could be better.
This optimizes LocalDate.plusDays for the common case of adding a small number of days.

JDK-8066291 - ZoneIdPrinterParser can be optimized.
The method ZoneRulesProvider.getAvailableZoneIds() now returns an immutable set, not a mutable one. Since most user code calls ZoneRules.getAvailableZoneIds(), it will be unaffected.

Thanks

Thanks for all these bug fixes and enhancements go to the many contributors, both inside and outside Oracle. (I've mostly been a reviewer, rather than an author, which has worked pretty well overall.)

Summary

The java.time.* keep on moving forward. Any feedback or other enhancement suggestions are welcome!

Tuesday, 1 July 2014

ThreeTen-Backport vs Joda-Time

So which project should you choose? ThreeTen-Backport or Joda-Time?

Date and Time libarary pre-Java 8

Over the years, I have produced two libraries for Java date and time.

The first is Joda-Time, a library has become the de facto standard choice for many users.

The second is JSR-310, included as java.time in Java SE 8. Today I released v1.0 of ThreeTen-Backport, which makes the same JSR-310 API available in Java SE 6 and 7, although it is under a different package name.

So which should you choose?

If you are on Java SE 8 then you should use java.time (JSR-310). It tackles many issues with Joda-Time and is better integrated with the rest of the Java core libraries. Where necessary, consider using ThreeTen-Extra for any additional functionality that isn't in the JDK.

If you are on Java SE 6 or 7, then in general you should use Joda-Time. It is the standard option that other teams will be using, and it will be easier to interoperate if you stick to using Joda-Time.

The main use case for ThreeTen-Backport is if your team is using Java SE 6 or 7 but you are planning on moving to Java SE 8 in the near future. In this case, using the backport can smooth your future migration. However it will still require a package rename for your API users.

Another use case for the backport is to assist with backporting other Java SE 8 code to Java SE 7. See the retrolambda project (which could use ThreeTen-Backport but doesn't).

I hope that helps you to decide!

Monday, 10 February 2014

New project: ThreeTen-Extra for JDK 8

JDK 8 includes JSR-310, a new date and time library. But what about functionality that didn't make it into the JDK?

ThreeTen-Extra

The main ThreeTen project is now essentially complete. The project was developed and delivered via JSR-310 into OpenJDK and JDK 8.

However, as part of that process, certain pieces of functionality were rejected and/or excluded from the JDK. This was sometimes due to scope management and sometimes due to whether something was appropriate for the JDK.

The TheeTen-Extra project provides a home for that functionality.

ThreeTen-Extra is a project on GitHub that provides additional functionality. It is delivered via Maven Central and is dependent on JDK 8.

The following functionality is currently provided:

  • DayOfMonth temporal value type
  • DayOfYear temporal value type
  • AmPm temporal enum
  • Quarter temporal enum
  • YearQuarter temporal value type
  • Days, Months and Years amount value types
  • Next/previous day adjusters that skip the weekend (Saturday/Sunday)
  • Coptic calendar system
  • Support for the TAI and UTC time-scales

The project has spare space to add more functionality, so long as it is generally applicable. For example, additional calendar systems would be a good fit. Feel free to raise a pull request with your ideas.

Summary

The ThreeTen-Extra project is now available, providing an additional jar file of date/time code that builds on java.time (JSR-310) in JDK 8.

Comments welcome!

Tuesday, 6 November 2012

Pitfalls of "consistent with equals"

The equals() method and the compareTo() method on Comparable are two of the most basic in Java. Yet their definitions have an interesting wrinkle around the concept of "consistent with equals".

The equals() method

The equals() method is both well defined and unclear in Java. It is well-defined in that it specifies exactly how the check for equal must work. They must be reflexive, symmetric, transitive, consistent and handle null.

However the equals() is also unclear. The Javadoc says that the method "Indicates whether some other object is "equal to" this one". Note the "equal to" part is in quotes. The key here is that it does not define how the equality should be determined. There are three standard choices:

  • the identity of the object (==), which is the default inherited from Object
  • the entire observable state of the object, such that if two objects are equal then one is substitutable for the other in other parts of the application
  • some subset of the information that makes logical sense to check equals on, such as an ID

The compareTo() method

The Comparable interface defines the concept of comparability. The Javadoc specifies that it "imposes a total ordering on the objects of each class that implements it".

Classes that implement Comparable have a natural ordering and can be sorted easily and used in collections like TreeSet and TreeMap without a separate Comparator.

The interface is well-defined, in that it specifies that the implementation must ensure a form of symmetry and transitive behaviour, just like equals(). It does not specify exactly how the comparison should be made, but defines the concept of consistency with equals.

Consistent/Inconsistent with equals

The Comparable interface says the following:

The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C.

Basically, this requires that the concept of equals defined by compareTo is the same as that defined by equals() (apart from nulls). This is at first glance a simple requirement but, as I'm going to discuss, it has complications.

This kind of definition is especially useful when considering operator overloading. If we consider a Java-like language where == is not object identity, but comparison using a method, and the greater-than/less-than operators are also available the question is what method to call. Greater-than/less-than would in this Java-like language naturally be based on compareTo() and == would call equals().

  // our new Java-like language
  if (a < b) return "Less";      // translation ignoring nulls: if (a.compareTo(b) < 0)
  if (a > b) return "Greater";   // translation ignoring nulls: if (a.compareTo(b) > 0)
  if (a == b) return "Equal";    // translation ignoring nulls: if (a.equals(b))
  throw new Exception("Impossible assuming no nulls?");

But if compareTo() is "inconsistent with equals" then this code can throw the exception, because a.compareTo(b) can return zero when a.equals(b) is false.

Other problems can occur in collections like TreeMap:

  // Foo class is "inconsistent with equals"
  assert foo1.equals(foo2) == false;
  assert foo1.compareTo(foo2) == 0;
  
  TreeMap<Foo, String> map = ...
  map.put(foo1, "a");
  map.put(foo2, "b");

Here the two objects are not equal using equals() but are equal using compareTo(). In this case, the map will have size one, not size two!

Because of the problems with being "inconsistent with equals", the Javadoc says It is strongly recommended (though not required) that natural orderings be consistent with equals.

Many JDK classes implementing Comparable do so in a manner "consistent with equals". These include Byte, Short, Integer, Long, Character and String.

Some others are more interesting:

  • BigDecimal - well-known to be "inconsistent with equals", as 4.00 is not equal to 4.0, but do compare the same
  • Double/Float - provides an explicit sort order and equals check for positive and negative zero and NaN to ensure compareTo is "consistent with equals"
  • CharSet - based on the ID/name. equals is case-senstitive, while compareTo is not, although as the names are normalized it tends not to matter - dubiously "consistent"
  • *Buffer (nio) - based on remaining content of the buffer. equals and compareTo appear to be "consistent" under my testing
  • Rdn (ldap) - based on the normalized form of the state, thus is "consistent with equals"
  • ObjectStreamField (serialization) - based on the name, but with primitives sorted first. equals is not overriden, so is "inconsistent with equals"
  • ObjectName (jmx) - equals based on the canonical name, compareTo defined as "not completely specified but is intended to be such that a sorted list of ObjectNames will appear in an order that is convenient for a person to read"! "inconsistent with equals"
  • FileTime (io) - implements equals using compareTo, definitely "consistent with equals"
  • File (io) - OS-specific, implements equals using compareTo, definitely "consistent with equals"
  • URI - source code appears to be "consistent with equals"
  • UUID - source code for equals includes variant that compareTo doesn't, but it appears to be unessesary code with no effect such that it is "consistent with equals"
  • Date (java.util) - source code difficult to follow because equals changes the state of the object (normalizing the deprecated setters), whereas compareTo does not change the state. As both ultimately so the same calculation it is "consistent with equals"
  • Date/Time (sql) - subclass java.util.Date and add nothing new, so are also "consistent with equals"
  • Timestamp (sql) - horrible compareTo and equals implementations that break the contracts, but is "consistent with equals" when comparing two Timestamp objects
  • Calendar/GregorianCalendar - equals compares the state, while compareTo compares along the time-line. Definitely "inconsistent with equals"

Note: In almost all cases, I had to examine the source code or write test code to determine whether a class was or was not "consistent with equals". There is a good Adopt-a-JDK task here to clarify the Javadoc and check UUID equals.

JSR-310

Having seen too many issues around BigDecimal, the plan has been for JSR-310 classes to be "consistent wth equals". However, a recent thread shows how controversial this can get.

Basically, it seems really simple to define equals/compareTo for some classes. LocalDate is just a date in a single calendar system, so has an obvious ordering and equals. LocalTime is just a time, so has an obvious ordering and equals. Instant is just an instantaeous point on the time-line, so has an obvious ordering and equals.

However other cases are not so obvious. Consider OffsetDateTime:

  dt1 = OffsetDateTime.parse("2012-11-05T06:00+01:00");
  dt2 = OffsetDateTime.parse("2012-11-05T07:00+02:00");

These two date-time objects represent the same instantaneous point on the time-line. But they have different local times and different offsets from UTC/Greenwich.

So, one question to readers.... which of these options do you prefer...

  1. dt1 not equal to dt2, compareTo() takes into account the local time and offset, "consistent with equals" (with a separate Comparator to sort by instant)
  2. dt1 not equal to dt2, compareTo() based on the instantaneous point on the time-line, "inconsistent with equals"
  3. dt1 equal to dt2, compareTo() based on the instantaneous point on the time-line, "consistent with equals"
  4. dt1 equal to dt2 and do not implement Comparable
  5. dt1 not equal to dt2 and do not implement Comparable

Personally I struggle with the idea that dt1.equals(dt2) would be true, but I'm open to opinions.

BTW, the question could also be posed with respect to BigDecimal. If you could to make that class "consistent with equals" would you change the equals() method or the compareTo() method?

Thursday, 6 October 2011

Time-zone database down

Today (2011-10-06), the time-zone database was closed down.

It is perhaps easy to read that line, think it doesn't affect you, and then move on. But thats just not the case.

Update 2011-10-07: A backup copy of the mailing list and subscribers has now swung into operation run by volunteer Robert Elz. Please only join this list to discuss changes to time-zones - its not a "fighting the lawsuit" list. New tz list

Update 2011-10-07: More details on the history of ACS, Astrolabe and how this came about from a competitor. Worth reading.

Update 2011-10-10: A new version of the time-zone database 2011l has been released. This news indicates how other members of the community have stepped up and continued the work, so the database can no longer be considered to be "down". However, we all need to ensure that we continue to support Olson and Eggert in their fight with the foolish people at Astrolabe. My blog about the rebooted database.

Update 2011-10-26: The situation has now stabilised. The database is now hosted by IANA after the succesful database reboot. Astrolabe also gave their opinion on the matter.

The time-zone database (sometimes referred to as the Olson database) is the computing world's principle source of time-zone data. It is embedded in every Unix and Java for starters, and will be used by many websites and probably by your iPhone. You may know it via the IDs, such as "Europe/London" or "America/New_York".

But, perhaps you're thinking that time-zones don't change? Well that may be true for America and the EU right now, but certainly isn't for the rest of the world. Governments change their time-zones all the time, and the decisions are frequently very political. I'd estimate there are between 20 and 100 separate changes made around the globe each year. And these can be at very short notice, triggered by earthquakes for example.

The time-zone database tracks all this information and creates a standard format file that describes it. I would show you an example of the file, but then perhaps I'd be sued....

The database itself was run as an open source project, led by Arthur David Olson, supported by many others. The data was published as a set of files about 15 times a year, and then picked up by users everywhere.

The complaint itself comes from Astrolabe, Inc, whose website looks like a company I would avoid doing business with.

The complaint is that Astrolabe produce a work, the "ACS Atlas", which is referenced by the time-zone database (some sources suggest that Astrolabe may have recently purchased the work). Astrolabe claim copyright over their work and thus believe that the time-zone databse should not have released their information to the public domain. The case is targetted at two private individuals - Arthur David Olson and Paul Eggert, who have hosted the website for many years.

The key passage in the time-zone database files is this:

# From Paul Eggert (2006-03-22):
# A good source for time zone historical data in the US is
# Thomas G. Shanks, The American Atlas (5th edition),
# San Diego: ACS Publications, Inc. (1991).
# Make sure you have the errata sheet; the book is somewhat useless without it.
# It is the source for most of the pre-1991 US entries below.

For obvious reasons, I'll refrain on commenting on the rights and wrongs of the case, although I will note that facts like the phonebook cannot be copyrighted. A detailed response from one site taken down is now available. Instead I'll focus on the impact.

The impact of this is severe for anyone that uses it - whether via Java, Unix or some other means. This really is the key tool used by everyone to tell the right time globally. We all owe a debt of gratitude to the database maintainers who have worked on this for many, many years at zero cost to the industry and for zero financial gain.

So, right now the global situation is that there is no longer a single central location for time-zone information for computing. I'm sure that each major user project (like the Unix distros) will patch their own versions as best they can, but the stricter ones might argue that the current data is tainted and want to remove even that. This could get very messy very quickly.

Both Joda-Time and ThreeTen/JSR-310 use the data to build timezone information. ThreeTen/JSR-310 in particular provides this information in huge detail to applications. The worst case scenario is that multiple groups start up to provide this data in the future, and applications are then responsible for handling multiple competing data sources.

This data is so key to the world at this point that it needs to be formalised and run by a group with more legal and financial backing. Efforts had been ongoing to achieve this, but they may now be in jeopardy - who would want to take on a project being legally attacked?.

I hereby call on the industry leaders to help sort this out - IBM, Oracle, Apple, Google, RedHat I'm looking at you.
Update: I didn't include Microsoft here because Windows has its own time-zone data files.

In the meantime, could I please ask that anyone thinking of patching the data on a temporary basis, or trying to recreate it from scratch, re-uses the existing file format. There is no reason to believe that the C code or file format is tainted by the lawsuit, just the data. So, lets all please try to minimise the mess that could happen if everyone starts to go their own way.

Add a comment or a rant below!

Update 2011-10-07: Alternatively you can rant on their Facebook page, Website contact us page or Amazon book review (note that the book may be by a different company - its a little unclear).

Thursday, 30 December 2010

What about JSR-310?

So, if the Java Community Process is now a zombie Java Corporate Partnership, what should I do with JSR-310?

JSR-310

I've been highly critical of Oracle's stewardship of Java, particularly on the topic of the JCP. Choosing to U-turn on their previous public statements and force through the Java SE 7 and 8 JSRs was bad for Java and bad for Oracle. By accepting Oracle's actions, the remaining JCP executive committee members ended the notion of the JCP as an open standards body.

So, the question arises as to whether I should cut my ties with the JCP and terminate JSR-310.

The reasons to abandon the JSR are quite compelling:

  • The JCP is no longer an open standards body.
  • JSRs now exist that are in incompatible with the JSPA legal agreement.
  • The Executive Committee has shown itself to be more willing to do Oracle's bidding than to hold them to account.

However, I must also ask what the result would be if I stopped the JSR:

  • I would break a commitment I made to the community to improve dates and times in Jave SE.
  • Someone else might take over the project, perhaps causing another poor Java SE date and time library.
  • The majority of developers, those that don't read blogs and news sites, don't care about the corporate politics and would suffer without ever knowing why.

Ever been between a rock and a hard place?

The upside is that the process of the JCP provides all the power to the specification lead. So, since I, and Michael Nascimento, are the specification leads for JSR-310, we have all the power :-) Consider what I said when the JCP asked me about transparency:

Anyone can access these javadoc files by just clicking a link on the JSR 310 website at java.net. Stephen says, "We always intended to run the JSR as an open source project. That naturally means public code, and feedback. Collecting the feedback is easier if people can access it by the method they are most familiar with -- javadoc." Some Spec Leads may be reluctant to run their projects as openly as this, but Stephen has no qualms at all. He says, "It's often thought that being open will increase the mails and issues you have to deal with. The reality is that you tend to have to address the real issues earlier than you might otherwise have to, and that is a very good thing."

The key phrase is "run the JSR as an open source project". Because if the JSR is an open source project then the status of the JCP is more of a detail, an annoyance.

So, while my heart might tell me to walk away from the zombie JCP, my head tells me that I really don't need to. This is just an open source project which the community badly needs. And the JCP is just a tool I can use to access Java SE 8. I dislike maven as a tool, yet I still use it - I can dislike the JCP and still use it in exactly the same way.

Therefore, I've decided to continue work on JSR-310, targetting Java SE 8.

I've also taken advantage of the impending destruction of the original java.net website to move the code and discussion to sourceforge, where I hold most of my other projects.

I've also chosen to give the reference implementation a real name - ThreeTen. So, the ThreeTen project is the reference implementation of JSR-310. Development of both the reference implementation and the JSR will occur at the ThreeTen project.

As part of this process I've attempted to clarify the legal position of contributions to the project, including discussion, without getting too legal. The concept is that the overriding principle is that the project works on trust and respect for the public good. Beyond that, version controlled contributions continue to use the BSD 3-clause license, and version controlled contributions destined for JSR-310 continue to require a contributor agreement. As such, existing mailing list subscribers need to resubscribe to the new mailing list.

I also leave open the option of writing a ThreeTen specification separate to the JSR-310 specification.

The aim of a ThreeTen specification would be to provide common terminology and behaviour at a higher level with the intention of sharing the knowledge gained to other areas of computing. This might be another language, library or specification, such as SQL or XML.

Finally, I'm pleased to confirm that I will continue to spend 20% of my work hours on ThreeTen/JSR-310 thanks to my employer OpenGamma where the project is a core part of their platform for financial analytics and risk management.


Stephen Colebourne
Project lead, ThreeTen
Co-spec lead, JSR-310

Monday, 8 February 2010

New job - impact on JSR-310

This is a quick blog to outline my upcoming job change and how it affects JSR-310.

For many years I've worked for SITA, global leader in air transport communications and IT solutions. But the time has come to move on, so from the 1st of March I'm starting a new job at a London startup, Open Gamma.

So, what can I tell you about Open Gamma? Well not too much just yet as its only just coming out of stealth mode. I can say they're lead by Kirk Wylie, they're building technology for the financial industry, and I'm excited about their big idea! Oh, and they're hiring (London only).

And how does this affect JSR-310?

Well, OpenGamma will be actively supporting my work on JSR-310 in work time! Clearly this will have a big impact on development pace, and we may yet make JDK 7 (but of course thats up to the SunOracle).

In the meantime, watch out for the Early Draft Review of JSR-310 where I'll need maximum feedback!

Friday, 20 November 2009

Why JSR-310 isn't Joda-Time

One question that has been repeatedly asked is why JSR-310 wasn't simply the same as Joda-Time. I hope to expain some reasons here.

Joda-Time as JSR-310?

At its heart, JSR-310 is an effort to add a quality date and time library to the JDK. So, since most people consider Joda-Time to be a quality library, why not include it directly in the JDK?

Well, there is one key reason - Joda-Time has design flaws.

Now before everyone panics and abuses that line as a tweet, I need to say that Joda-Time is by far the best option curently available, and that most users won't appreciate the design flaws. But, I do want to document them, so the basis for the changes in JSR-310 is clear.

1) Human/Machine timelines

One element of clarity is a better understanding of the distinction between the two principle views of the timeline - Human and Machine.

Machines have one view - a single, ever increasing number. In Java we set zero as 1970-01-01T00:00Z and count in milliseconds from there.

Humans have a totally different view of time. We have multiple calendar systems (one primary, many others), which divide the timeline into years, months, days, hours, minutes and seconds. In addition, humans have time zones which cause the values to vary around the globe, and for there to be gaps and overlaps in the human timeline as DST starts and ends.

Much of the time, a conversion between the two timeline views is possible with a time zone, however in a DST gap or overlap, things are much less clear.

Joda-Time defines two key interfaces - ReadableInstant and ReadablePartial. Both the Instant class (simple instant in time) and the DateTime class (human view of an instant in time) are implementations of ReadableInstant. This is wrong.

DateTime is a human-timeline view of the world, not a machine-timeline view. As such, DateTime is much better thought of, and designed as, a LocalDateTime and a timezone rather than the projection of the machine timeline onto the human timeline. Thus, DateTime should not implement ReadableInstant.

2) Pluggable chronology

What is the range of values returned by this method in Joda-Time?:
int month = dateTime.getMonthOfYear();
The answer is not 1 to 12, but could be 1 to 13! (yet January is still 1 and December is 12)

The answer to this puzzler is down to pluggable chronologies. Each date/time class in Joda-Time has a pluggable chronology. This defines the calendar system that is in use. But most users of the API never check to see if the chronology is the standard ISO/ chronology before calling getMonthOfYear(). Yet, the Coptic chronology has 13 months in a year, and thus can return a range of 1 to 13.

A better solution would be to keep the date/time classes restricted to a single calendar system. That way, the result from each method call is clear, and not dependent on any other state in the class, like the chronology.

3) Nulls

Joda-Time accepts null as a valid value in most of its methods. For date/times it means 1970-01-01T00:00Z. For durations it means zero. For peiods it means zero.

This approach causes random bugs if your code happens to provide a null to Joda-Time that you hadn't originally planned for. Instead of throwing an error, Joda-Time continues, and the resulting date/time is going to be different from what you want.

4) Internal implementation

Certain aspects of the internal implementation are complex, and the result of having pluggable chronologies and a misunderstanding of the machine/human divide in the timeline. Changing this is a big change to the code.

One particular area of trouble is managing DST overlaps. The behaviour in Joda-Time of these isn't that well defined.

Summary

Joda-Time isn't broken!

It does the job it was designed for, and does it much better than the JDK. And it is widely used and without too many major issues. However, after a few years, it is now clear where it could be designed better.

I took the decision that I didn't want to add an API to the JDK that had known design flaws. And the changes required weren't just minor. As a result, JSR-310 started from scratch, but with an API 'inspired by Joda-Time'.

I hope that explains the thought process behind the creation of a new API in JSR-310.

Friday, 5 October 2007

JSR-310 and Java 7 language changes

Part of the difficulty I'm finding with designing JSR-310 (Dates and Times) is that I constantly come across gaps in the language of Java. My concern is that these gaps will shape the API to be less than it should be. Let me give some examples:

BigDecimal

JSR-310 is considering adding classes representing durations. (So is JSR-275, but thats another story.)

The aim of the duration classes is to meet the use case of representing "6 days", or "7 minutes". As a result, the first set of code uses int to represent the amount.

 public class Days {     // code is for blog purposes only!
   private int amount;
   ...
 }

However, what happens when you get down to seconds and milliseconds? Do we have one class that represents seconds, and a separate class that represents milliseconds? That seems rather naff. What would be better is to have a class to represent seconds with decimal places:

 public class Days {
   private double amount;
   ...
 }

But double is a no-no. Like float, it is unreliable - unable to represent some decimal values, and with sometimes unexpected answers from the maths. Of course, the answer is BigDecimal:

 public class Days {
   private BigDecimal amount;
 }

So, why am I, and others, reticent to use this 'correct' solution? Its because we don't have BigDecimal literals and operators. This is a clear case where language-level choices are affecting library-level design for the worse.

Immutables

JSR-310 is based around immutable classes, which are now a well recognised best practice for classes like dates and times. Unfortunately, the Java language is not well setup for immutable classes.

Ideally, there should be language level support for immutable classes. This would involve a single keyword to declare a class as immutable, and could allow certain runtime optimisations (so I'm told...).

 public immutable class DateTime {
   ...
 }

Unfortunately, it is probably too late for Java to do much on this one.

Self types

Another missing Java feature affecting JSR-310 is self-types. These are where a superclass can declare a method that automatically causes all subclasses to return the same type as the subclass:

 public abstract class AbstractDateTime {
   public <this> plusYears(Duration duration) {
     return factory.create(this.amount + duration);   // pseudo-code
   }
 }
 public final class DateTime extends AbstractDateTime {
 }
 // usage
 DateTime result = dateTime.plus(duration);

The thing to note is the 'this' generic style syntax. The effect is that the user of the subclass was able to use the method and get the correct return type. They were returned a DateTime rather than a AbstractDateTime.

This can be achieved today by manually overriding the method in each and every subclass. However that doesn't work if you want to add a new method to the abstract superclass in the future and have it picked up by every subclass (which is what you want in a JSR, as a JSR doesn't have a perfect crystal ball for its first release).

Again, a language-level missing feature severely compromises a library-level JSR.

Operator overloading

Another area where JSR-310 may choose the 'wrong' approach is int-wrapper classes. For JSR-310 this would be a class representing a duration in years.

If I were to give you a problem description that said you need to model 'the number of apples' in a shop', and to be able to add, subtract and multiply that number, you'd have a couple of design options.

The first option is to hold an int and perform regular maths using +, - and *. The downside is that only javadoc tells you that the int is a number of apples, instead of a number of oranges. This is exactly the situation before generics.

The second option is to create an Apples class wrapping the int. Now, you cannot confuse apples with oranges. Unfortunately, you also cannot use +, - and *. This is despite the fact that they are obviously valid in this scenario. Using plus/minus/multipliedBy/dividedBy methods just doesn't have the same clarity.

Given this choice today, most architects/designers seem to be choosing the first option of just using an int. Language designers should really be looking at that decision and shaking their head. The whole point of the generics change was to move away from reliance on javadoc. Yet here, in another design corner, people still prefer a lack of real safety and javadoc to 'doing the right thing'. Why? Primarily because of the lack of operator overloading.

Ironically, I think this is an area that really might change in the future. But if JSR-310 has chosen to use int rather than proper classes by that point, a great opportunity will have passed.

Summary

My assertion that language-level features (or rather missing features) affect library design isn't really news. The interesting thing with JSR-310 is just how constraining the missing features are proving to be.

The trouble is that with no clear idea on where the future of the Java language lies, a JSR like 310 cannot make good choices which will fit well with future language change. The danger is that we simply create another date and time library that doesn't fit well with the Java language of 2010 or later.

Opinions welcome on whether JSR-310 should completely ignore potential language changes, or try to make a best guess for the future.

Monday, 2 July 2007

JSR-310 - What running a JSR really means

Choosing to take on the development of a JSR (JSR-310, Date and Time API) wasn't an easy decision. I knew at the start that it would involve a lot of effort.

My original plan was to work on the JSR solely in my free time (evenings and weekends), but after 4 months the reality was that I hadn't got enough done. So thats why, starting today, I'm taking unpaid leave two days a week from my day-job for 3 months to try and get the task done.

So, I guess that this post should serve as a warning to anyone thinking of starting a JSR. Its going to cost you :-)

PS. JSR-310 is run in a fully open manner, so if you've got something to contribute to the debate, please join the mailing list or add to the wiki!

Wednesday, 9 May 2007

JavaOne JSR-310 Date and Time API BOF tonight!

If you're at JavaOne and hate Date and Calendar then come along to our BOF tonight! Its at 21:55 in MC105 - BOF-2794.

We'll be having a short talk about what's wrong with Date and Calendar, what current alternatives are out there and outline the initial thoughts of the JSR group. There will also be a mini-puzzler with mini-chocolate reward!!!

The main aim of the BOF is to have a discussion however - what calendar systems should we support, what kind of API, should we address SQL access? We'd love to hear your input, so come along if you can!

Tuesday, 30 January 2007

Announcing JSR 310 - Date and Time API

For too long we've suffered the Date and Calendar APIs in Java. No more, I say, No more!

I am pleased to be able to announce JSR 310 - Date and Time API. Here's the summary of what the JSR is aiming for:

This JSR will provide a new and improved date and time API for Java. The main goal is to build upon the lessons learned from the first two APIs (Date and Calendar) in Java SE, providing a more advanced and comprehensive model for date and time manipulation.

The new API will be targeted at all applications needing a data model for dates and times. This model will go beyond classes to replace Date and Calendar, to include representations of date without time, time without date, durations and intervals. This will raise the quality of application code. For example, instead of using an int to store a duration, and javadoc to describe it as being a number of days, the date and time model will provide a class defining it unambiguously.

The new API will also tackle related date and time issues. These include formatting and parsing, taking into account the ISO8601 standard and its implementations, such as XML. In addition, the areas of serialization and persistence will be considered.

The final goal of the new API is to be simple to use. The API will need to contain some powerful features, but these must not be allowed to obscure the standard use cases. Part of being easy to use includes interaction with the existing Date and Calendar classes, something that will be a key focus of the Expert Group.

Obviously, this whole JSR will be influenced by Joda-Time, the open source library that I've been working on for the last few years. However, the JSR will not be a simple adoption of Joda-Time. For a start the Java 5 language features make a difference. And there are probably a few rough edges that can be smoothed out too. But overall, its a very solid base to begin from.

The JSR will be run by myself and Michael Nascimento Santos. I also want to thank our extensive list of supporters (19!) without whom we wouldn't have got to this point.

The aim in running the JSR is to be as open and transparent as possible. There will be a java.net project with a mailing list available for anyone to sign up to. We also aim to have a publicly readable Subversion repository. Joda-Time worked well as open-source - why shouldn't the JSR?

So, if you're interested in helping us move Java beyond Date and Calendar, then please consider joining the public mailing list or Expert Group (via JCP). Alternatively, feel free to leave comments here.

Thursday, 6 July 2006

A better datetime library JSR?

Do you hate the JDK Date and Calendar classes? Would you like to see an alternative in the JDK? Or are you happy with the JDK classes? Maybe you are happy with pulling in a jar file?

I ask because I get asked from time to time whether Joda-Time is going to get a JSR. Each time this comes up I point out that its a lot of work to do in my free time, and there are infrequent enough releases as is!

So, this blog is an open question - is it worth it? Should JDK7 contain a better datetime library? Please add a comment with your views, postive and negative so I can get some idea of peoples thoughts!

Friday, 4 March 2005

So where next with Joda-Time? A JSR?

Releasing a v1.0 can be a strange experience. Once its done, the stress can just disappear, and you take a bit of a rest (assuming there was no great heap of new bugs discovered, which there wasn't).

And its a bit like that with Joda-Time. v1.0 is done and out in the wild. There was quite a bit of positive feedback, but I've no idea how popular it really was because Sourceforge statistics are up the spout.

The main question then becomes well what next? v1.1 would be the obvious answer, but I need to gather some energy to add more code. And until and unless I get feedback on Joda-Time in use its difficult to know what people are missing.

The other possible direction is a JSR. Various people have suggested this, but I am a little skeptical. JDOM, Jade (scientific units) and Groovy haven't exactly been good indicators of what JSRs do to open source projects.

So, what do people reading this think. Are you not using Joda-Time because its not in the JDK? Is a JSR a good direction to go? Have you got your own ideas for what java.time should look like?