You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+12-4Lines changed: 12 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,13 +13,13 @@ Feature of CFTime include:
13
13
14
14
* Time instances as defined [Climate and Forecasting (CF) conventions](https://cfconventions.org/)
15
15
* 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.
18
18
* Basic arithmetic such as computing the duration between two time instances
19
19
* 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.
21
21
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.
*[NanoDates.jl](https://github.com/JuliaTime/NanoDates.jl): Dates with nanosecond resolved days
151
153
*[TimesDates.jl](https://github.com/JeffreySarnoff/TimesDates.jl): Nanosecond resolution for Time and Date, TimeZones
152
154
*[AstroTime.jl](https://github.com/JuliaAstro/AstroTime.jl): Astronomical time keeping in Julia
153
155
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
+
154
162
## Acknowledgments
155
163
156
164
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.
Copy file name to clipboardExpand all lines: docs/src/index.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -79,6 +79,9 @@ dayofyear
79
79
80
80
## Convertion Functions
81
81
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
+
82
85
The `convert` function can be used to convert dates between the different calendars:
Copy file name to clipboardExpand all lines: paper/paper.md
+8-53Lines changed: 8 additions & 53 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,17 +23,16 @@ bibliography: paper.bib
23
23
24
24
25
25
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.
27
26
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)).
28
27
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.
30
29
31
30
32
31
# Statement of need
33
32
34
33
In many Earth science disciplines and beyond, expressing a time instance and a duration is essential. The CF conventions provide a rich and flexible
35
34
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.
37
36
38
37
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].
39
38
@@ -59,75 +58,31 @@ The CF conventions define several calendar types, including:
|`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 |
64
63
|`noleap`, `365_day`|`DateTimeNoLeap`| calendar without leap years |
65
64
|`all_leap`, `366_day`|`DateTimeAllLeap`| calendar with only leap years |
66
65
|`360_day`|`DateTime360Day`| calendar assuming that all months have 30 days |
67
66
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
-
71
67
CFTime is based on the Meeus' algorithm [@Meeus98] for the Gregorian and Julian calendars, with two adaptations:
72
68
73
69
* The original algorithm is based on floating-point arithmetic. The algorithm in CFTime is implemented using integer arithmetic, which is more efficient.
74
70
Additionally, underflows and overflows are easier to predict and handle with integer arithmetic.
75
71
* The Meeus' algorithm has been extended to dates prior to 100 BC.
76
72
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
-
80
73
The following is a list of the main features of CFTime:
81
74
82
75
* 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.
99
79
100
80
# Acknowledgements
101
81
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.
103
83
104
84
# Funding
105
85
106
86
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.
0 commit comments