Skip to content

Commit 6d50f5b

Browse files
shorten paper and move some info to documentation
1 parent c28cbf1 commit 6d50f5b

File tree

3 files changed

+23
-57
lines changed

3 files changed

+23
-57
lines changed

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ Feature of CFTime include:
1313

1414
* Time instances as defined [Climate and Forecasting (CF) conventions](https://cfconventions.org/)
1515
* Supporting a wide range of the time resolutions, from days down to attoseconds (for feature parity with NumPy's date time type)
16-
* Supporting arbitrary time origins
17-
* By default, the time counter is a 64-bit integer, but other integers types (such as `Int32`, `Int128` or `BigInt`) or floating-point types can be used (not recommended)
16+
* Supporting arbitrary time origins. For CFTime.jl the time origin is part of the parametric type definition and not an additional field of the time data structure. As a consequence, a large array of date times with common time origin only need to store the time counter (64-bit integer by default) for every element, which makes this case as memory efficient as NumPy's or Julia's default date time for this common use case.
17+
* By default, the time counter is a 64-bit integer, but other integers types (such as `Int32`, `Int128` or `BigInt`) or floating-point types can be used. Using an integer to encode a time instance is recommended for most applications, as it makes reasoning about the time resolution easier.
1818
* Basic arithmetic such as computing the duration between two time instances
1919
* Conversion function between CFTime types and Julia's `DateTime`.
20-
* Time ranges
20+
* Regular time range based on Julia's range type. A time range is a vector of date time elements, but only the start time, the end time and the steps need to be stored in memory.
2121

22-
Leap seconds are currently not supported by `CFTime.jl`.
22+
`CFTime.jl` currently does not support leap seconds, which were standardized as part of CF conventions version 1.12, released in December 2024.
2323

2424
## Installation
2525

@@ -147,10 +147,18 @@ Dates.year(dt),Dates.month(dt),Dates.day(dt)
147147

148148
## Alternatives
149149

150+
Julia packages:
151+
150152
* [NanoDates.jl](https://github.com/JuliaTime/NanoDates.jl): Dates with nanosecond resolved days
151153
* [TimesDates.jl](https://github.com/JeffreySarnoff/TimesDates.jl): Nanosecond resolution for Time and Date, TimeZones
152154
* [AstroTime.jl](https://github.com/JuliaAstro/AstroTime.jl): Astronomical time keeping in Julia
153155

156+
Outside of the julia ecosystem:
157+
158+
* [cftime](https://unidata.github.io/cftime/) for python
159+
* [CFtime](https://CRAN.R-project.org/package=CFtime) for R
160+
161+
154162
## Acknowledgments
155163

156164
Thanks to Jeff Whitaker and [contributors](https://github.com/Unidata/cftime/graphs/contributors) for python's [cftime](https://github.com/Unidata/cftime) released under the MIT license which has helped the developpement of this package by providing reference values and a reference implementation for tests. The algorithm is based on Jean Meeus' algorithm published in Astronomical Algorithms (2nd Edition, Willmann-Bell, p. 63, 1998) adapted to years prior to 300 AC.

docs/src/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ dayofyear
7979

8080
## Convertion Functions
8181

82+
83+
The flexibility of CFTime's datetime (related to the time origin, time resolution and type of the time counter) comes with some cost. When merging data from different sources, the resulting merged time vector may not have a concrete type, as there is no implicit conversion to a common time origin or internal unit, unlike Julia's `DateTime`. In some cases, the user might decide to explicitly convert all times to a common time origin and internal unit for optimal performance.
84+
8285
The `convert` function can be used to convert dates between the different calendars:
8386

8487
```julia

paper/paper.md

Lines changed: 8 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,16 @@ bibliography: paper.bib
2323

2424

2525
Climate and Forecast (CF) conventions are a metadata standard for Earth data [@Eaton2024] and are mainly used in oceanography and meteorology.
26-
They aim to be equally applicable to model data, remote-sensing data and in-situ data, despite the high heterogeneity among data types.
2726
The CF conventions were originally proposed for the NetCDF storage format, but they are also increasingly used with other formats like Zarr [@OGC_Zarr] and GRIB ([GRIBDatasets](https://github.com/JuliaGeo/GRIBDatasets.jl)).
2827

29-
Since the initial release of the Climate and Forecast (CF) conventions [@Eaton2003], the encoding of time instances has been standardized. This part of the standard is based on the earlier COARDS (Cooperative Ocean Atmosphere Research Data Service) standard from 1995 [@COARDS]. The Julia package CFTime implements various standardized calendars that have been standardized in the frame of these conventions. It also supports some arithmetic operations for example, computing the duration between two time instances, ordering time instances and creating time ranges. The time origin and resolution are flexible ranging from days to attoseconds.
28+
Since the initial release of the Climate and Forecast (CF) conventions [@Eaton2003], the encoding of time instances has been standardized. The Julia package CFTime implements various calendars that have been standardized in the frame of these conventions. It also supports some arithmetic operations for example, computing the duration between two time instances, ordering time instances and creating time ranges. The time origin and resolution are flexible ranging from days to attoseconds.
3029

3130

3231
# Statement of need
3332

3433
In many Earth science disciplines and beyond, expressing a time instance and a duration is essential. The CF conventions provide a rich and flexible
3534
framework for handling time, equally applicable to observations and model data. To our knowledge, CFTime.jl is the only package in the Julia ecosystem that implements the time structures standardized by the CF conventions. While almost all datasets used in Earth Science use dates after the year 1582, some datasets or software systems use a time origin before this date, which makes it necessary to handle the transition from Julian to Gregorian calendar [@Octave; @SeaDataNet_format].
36-
Some users also expressed the need for microseconds and nanoseconds as time resolution. In particular, the popular Python package Pandas [@mckinney-proc-scipy-2010] defaults to nanoseconds as the time resolution. It was therefore necessary to also support sub-second time resolutions, even if they are rarely used in typical Earth science applications.
35+
Some users also expressed the need for microseconds and nanoseconds as time resolution even if they are rarely used in typical Earth science applications.
3736

3837
As of 31 March 2025, 119 Julia packages depend directly or indirectly on CFTime (excluding optional dependencies). CFTime is for example used by numerical models, such as ClimaOcean.jl, a framework for realistic ocean and coupled sea-ice simulations based on Oceananigans.jl [@OceananigansJOSS], the hydrological modeling package Wflow.jl [@vanVerseveld2024] and AIBECS.jl, a modeling framework for global marine biogeochemical cycles [@Pasquier2022].
3938

@@ -59,75 +58,31 @@ The CF conventions define several calendar types, including:
5958
| Calendar | Type | Explanation |
6059
| ----------------------- | ---------------------------- | ---------------------------- |
6160
| `standard`, `gregorian` | `DateTimeStandard` | the Gregorian calendar after 15 October 1582 and the Julian calendar before |
62-
| `proleptic_gregorian` | `DateTimeProlepticGregorian` | the Gregorian calendar applied to all dates (including before 15 October 1582) |
63-
| `julian` | `DateTimeJulian` | the Julian calendar applied to all dates (including after 15 October 1582) |
61+
| `proleptic_gregorian` | `DateTimeProlepticGregorian` | the Gregorian calendar applied to all dates |
62+
| `julian` | `DateTimeJulian` | the Julian calendar applied to all dates |
6463
| `noleap`, `365_day` | `DateTimeNoLeap` | calendar without leap years |
6564
| `all_leap`, `366_day` | `DateTimeAllLeap` | calendar with only leap years |
6665
| `360_day` | `DateTime360Day` | calendar assuming that all months have 30 days |
6766

68-
69-
The Gregorian calendar was introduced to account for the fact that a solar year is not exactly 365.25 days, but is more closely approximated by 365.2422 days. In the standard calendar, the day Thursday, 4 October 1582 (the last day of the Julian calendar) is followed by the first day of the Gregorian calendar, Friday, 15 October 1582 (the date of introduction of the Gregorian calendar).
70-
7167
CFTime is based on the Meeus' algorithm [@Meeus98] for the Gregorian and Julian calendars, with two adaptations:
7268

7369
* The original algorithm is based on floating-point arithmetic. The algorithm in CFTime is implemented using integer arithmetic, which is more efficient.
7470
Additionally, underflows and overflows are easier to predict and handle with integer arithmetic.
7571
* The Meeus' algorithm has been extended to dates prior to 100 BC.
7672

77-
The Meeus' algorithm is very compact, efficient, requires very few branches, and does not need large tables of constants. For verification purposes, the
78-
algorithm used in the cftime python package [@Whitaker2024] was ported to Julia, which is less efficient but significantly easier to audit for correctness.
79-
8073
The following is a list of the main features of CFTime:
8174

8275
* Basic arithmetic, such as subtracting two time instances to compute their duration, or adding a duration to a time instance.
83-
* Supporting a wide range of the time resolutions, from days down to attoseconds. Even if the use of attoseconds is quite unlikely in the context of earth science data, it has been added for feature parity with NumPy's date time type [@harris2020array; @numpy].
84-
* Supporting arbitrary time origins. Since the time origin for NumPy's date time type is fixed to be 1 January 1970 at 00:00, the usefulness of some time units is limited. As an extreme example, with attoseconds, all NumPy's date times can only express a time span of +/- 9.2 s around the time origin since a 64-bit integer is used internally. For CFTime.jl the time origin is arbitrary and part of the parametric type definition and not an additional field of the time data structure. As a consequence, a large array of date times with common time origin only need to store the time counter (also a 64-bit integer by default) for every element, which makes this case as memory efficient as NumPy's or Julia's default date time for this common use case.
85-
86-
* By default, the time counter is a 64-bit integer, but other integer types (such as 32-bit, 128-bit, or Julia's arbitrary-sized integer `BigInt`) or floating-point types can be used. Using an integer to encode a time instance is recommended for most applications, as it makes reasoning about the time resolution easier. Julia's compiler optimizes all functions and methods for the chosen types, ensuring optimal run-time performance.
87-
* Conversion function between CFTime types and Julia's `DateTime`.
88-
* Regular time range based on Julia's range type. A time range is a vector of date time elements, but only the start time, the end time and the steps need to be stored in memory.
89-
90-
91-
The flexibility of CFTime's datetime comes with some cost. When merging data from different sources with different time origins and units, the resulting merged time vector may not have a concrete type, as there is no implicit conversion to a common time origin or internal unit, unlike Julia's `DateTime`. In some cases, the user might decide to explicitly convert all times to a common time origin and internal unit for optimal performance. Another limitation is that CFTime currently does not support leap seconds, which were standardized as part of CF conventions version 1.12, released in December 2024.
92-
93-
# Similar software
94-
95-
This julia package, CFTime, has been highly influenced by Python's cftime [@Whitaker2024], which is also used in libraries such as xarray [@hoyer2017xarray].
96-
In the R ecosystem, the CFtime package serves a similar purpose and scope [@vanLaake2025] to this package.
97-
Among Julia packages, [NanoDates.jl](https://github.com/JuliaTime/NanoDates.jl) and [TimesDates.jl](https://github.com/JeffreySarnoff/TimesDates.jl) for representing time with a nanosecond precision and [AstroTime.jl](https://github.com/JuliaAstro/AstroTime.jl) for astronomical time scales should also be mentioned.
98-
76+
* Supporting a wide range of the time resolutions, from days down to attoseconds for feature parity with NumPy's date time type [@harris2020array; @numpy].
77+
* Supporting arbitrary time origins. Since the time origin for NumPy's date time type is fixed to be 1 January 1970 at 00:00, the usefulness of some time units is limited. As an extreme example, with attoseconds, all NumPy's date times can only express a time span of +/- 9.2 s around the time origin since a 64-bit integer is used internally.
78+
* By default, the time counter is a 64-bit integer, but other integer types or floating-point types can be used.
9979

10080
# Acknowledgements
10181

102-
I thank [all contributors](https://github.com/JuliaGeo/CFTime.jl/graphs/contributors) to this package, in particular Martijn Visser, Fabian Gans, Rafael Schouten and Yeesian Ng. I also acknowledge Jeff Whitaker and [contributors](https://github.com/Unidata/cftime/graphs/contributors) for Python's [cftime](https://github.com/Unidata/cftime) which has helped the development of this package by providing reference values and a reference implementation for tests.
82+
I thank [all contributors](https://github.com/JuliaGeo/CFTime.jl/graphs/contributors) to this package, in particular Martijn Visser, Fabian Gans, Rafael Schouten and Yeesian Ng. I also acknowledge Jeff Whitaker for Python's [cftime](https://github.com/Unidata/cftime) which has helped the development of this package by providing reference values and a reference implementation for tests.
10383

10484
# Funding
10585

10686
Acknowledgement is given to the F.R.S.-FNRS (Fonds de la Recherche Scientifique de Belgique) for funding the position of Alexander Barth. This work was partly performed with funding from the Blue-Cloud 2026 project under the Horizon Europe programme, Grant Agreement No. 101094227.
10787

10888
# References
109-
110-
<!-- LocalWords: CFTime jl julia netcdf orcid GHER Liège situ Zarr
111-
-->
112-
<!-- LocalWords: NetCDF grib GRIBDatasets COARDS nd gregorian Meeus
113-
-->
114-
<!-- LocalWords: DateTimeStandard proleptic julian DateTimeJulian
115-
-->
116-
<!-- LocalWords: DateTimeProlepticGregorian noleap DateTimeNoLeap
117-
-->
118-
<!-- LocalWords: DateTimeAllLeap DateTime cftime dataset SeaDataNet
119-
-->
120-
<!-- LocalWords: ClimaOcean Oceananigans hydrological Wflow AIBECS
121-
-->
122-
<!-- LocalWords: modelling biogeochemical NCDatasets gridded Printf
123-
-->
124-
<!-- LocalWords: YAXArrays OceanRobots ArgoData attoseconds numpy's
125-
-->
126-
<!-- LocalWords: datetime datetimes julia's BigInt timerange xarray
127-
-->
128-
<!-- LocalWords: CFTimes CFtime NanoDates TimesDates AstroTime de
129-
-->
130-
<!-- LocalWords: Acknowledgements Fonds Scientifique Belgique Gans
131-
-->
132-
<!-- LocalWords: Martijn Visser Schouten Yeesian Ng programme
133-
-->

0 commit comments

Comments
 (0)