CalCalcs and the udunits library

The udunits library is a handy set of routines that translate between different units. Also included in version 1 of the library were some routines to handle dates and times. In particular, routine utCalendar could convert temporal intervals into dates, for example, converting "3 days since 1901-01-01" into the date "1901-01-04". Routine utInvCalendar did the reverse transform, for example, converting the date "1901-01-04" into "3 days since 1901-01-01". You could specify the date the conversions were referenced to and the time interval, so you could as easily work in "milliseconds since 1875-09-15 12:00" or many other units.

The udunits library is widely used in the field of climate research, so I wrote utCalendar_cal and utInvCalendar_cal, which extended these routines to support the calendars typically used by climate models.


Version 2 of the udunits library

When version 2 of the udunits library was released, the new API did not include a direct replacement for the utCalendar/utInvCalendar functionality. Additionally, the documentation for the version 2 library states:

"I've come to believe, however, that creating such a unit [a calendar-referenced date unit] was a mistake, primarily because users try to use the unit in ways for which it was not designed (such as converting dates in a calendar whose year is exactly 365 days long). Such activities are much better handled by a dedicated calendar package. Please be careful about using timestamp-units."

In the source code itself, routine unitcore.c, a comment on the calendar-referenced date unit states:

"A wrong-headed unit that shouldn't exist but does for backward compatibility. It was intended to provide similar functionality as the GalileanUnit, but for time units (e.g., "seconds since the epoch"). Unfortunately, people try to use it for more than it is capable (e.g., days since some time on an imaginary world with only 360 days per year)."




The CalCalcs routines

The above make me concerned that support for the calendrical calculations might be dropped in a future version. And since I was rewriting the utCalendar_cal and utInvCalendar_cal routines to support the udunits library version 2 anyway, I figured I might as well replace all the calendar functionality of the udunits library.

Here is how I structured it.

The CalCalcs routines themselves work only in integer days, and use no code or calls to the udunits libray (either version 1 or 2). They are completely stand-alone. The are in their own file ("calcalcs.c") and have their own header ("calcalcs.h"), and can be compiled without linking to the udunits library.

The new routines utCalendar2, utCalendar2_cal, utInvCalendar2, and utInvCalendar2_cal both 1) provide a replacement for the old version 1 routines that work with the version 2 library; and 2) extend those new routines to calendars used by climate models. These routines use the udunits library only for conversion between time units, such as days to seconds, or seconds to hours. The do not use any udunits routines or calls for any calendrical computations. They are in a separate source and header file ("utCalendar2_cal.c" and "utCalendar2_cal.h"). If you use utCalendar2_cal.c you must also include calcalcs.c and link the result with the udunits library.

What this means is, in essence, that all support for calendars could be dropped from the udunits library and the CalCalcs routines, and the utCalendar2, utCalendar2_cal, utInvCalendar2, and utInvCalendar2_cal routines, would still work exactly the same.

(C) 2010 David W. Pierce