Ultra-precise date and time handling in Rust for scientific applications with leap second support
Project description
hifitime 3
Scientifically accurate date and time handling with guaranteed nanosecond precision for 32,768 years before 01 January 1900 and 32,767 years after that reference epoch.
Formally verified to not crash on operations on epochs and durations using the Kani
model checking.
Features
- Initialize a high precision Epoch from the system time in UTC
- Leap seconds (as announced by the IETF on a yearly basis)
- UTC representation with ISO8601 and RFC3339 formatting and blazing fast parsing (45 nanoseconds)
- Trivial support of time arithmetic: addition (e.g.
2.hours() + 3.seconds()
), subtraction (e.g.2.hours() - 3.seconds()
), round/floor/ceil operations (e.g.2.hours().round(3.seconds())
) - Supports ranges of Epochs and TimeSeries (linspace of
Epoch
s andDuration
s) - Trivial conversion between many time scales
- High fidelity Ephemeris Time / Dynamic Barycentric Time (TDB) computations from ESA's Navipedia
- Julian dates and Modified Julian dates
- Embedded device friendly:
no-std
andconst fn
where possible
This library is validated against NASA/NAIF SPICE for the Ephemeris Time to Universal Coordinated Time computations: there are exactly zero nanoseconds of difference between SPICE and hifitime for the computation of ET and UTC after 01 January 1972. Refer to the leap second section for details. Other examples are validated with external references, as detailed on a test-by-test basis.
Supported time scales
- Temps Atomique International (TAI)
- Universal Coordinated Time (UTC)
- Terrestrial Time (TT)
- Ephemeris Time (ET) without the small perturbations as per NASA/NAIF SPICE leap seconds kernel
- Dynamic Barycentric Time (TDB), a higher fidelity ephemeris time
- Global Positioning System (GPST)
- Galileo System Time (GST)
- BaiDou Time (BDT)
- UNIX
Non-features
- Time-agnostic / date-only epochs. Hifitime only supports the combination of date and time, but the
Epoch::{at_midnight, at_noon}
is provided as a helper function.
Usage
Put this in your Cargo.toml
:
[dependencies]
hifitime = "3.6"
Examples:
Time creation
use hifitime::{Epoch, Unit, TimeUnits};
use core::str::FromStr;
#[cfg(feature = "std")]
{
// Initialization from system time is only available when std feature is enabled
let now = Epoch::now().unwrap();
println!("{}", now);
}
let mut santa = Epoch::from_gregorian_utc_hms(2017, 12, 25, 01, 02, 14);
assert_eq!(santa.to_mjd_utc_days(), 58112.043217592590);
assert_eq!(santa.to_jde_utc_days(), 2458112.5432175924);
assert_eq!(
santa + 3600 * Unit::Second,
Epoch::from_gregorian_utc_hms(2017, 12, 25, 02, 02, 14),
"Could not add one hour to Christmas"
);
assert_eq!(
santa + 60.0.minutes(),
Epoch::from_gregorian_utc_hms(2017, 12, 25, 02, 02, 14),
"Could not add one hour to Christmas"
);
assert_eq!(
santa + 1.hours(),
Epoch::from_gregorian_utc_hms(2017, 12, 25, 02, 02, 14),
"Could not add one hour to Christmas"
);
let dt = Epoch::from_gregorian_utc_hms(2017, 1, 14, 0, 31, 55);
assert_eq!(dt, Epoch::from_str("2017-01-14T00:31:55 UTC").unwrap());
// And you can print it too, although by default it will print in UTC
assert_eq!(format!("{}", dt), "2017-01-14T00:31:55 UTC".to_string());
Time differences, time unit, and duration handling
Comparing times will lead to a Duration type. Printing that will automatically select the unit.
use hifitime::{Epoch, Unit, Duration, TimeUnits};
let at_midnight = Epoch::from_gregorian_utc_at_midnight(2020, 11, 2);
let at_noon = Epoch::from_gregorian_utc_at_noon(2020, 11, 2);
assert_eq!(at_noon - at_midnight, 12 * Unit::Hour);
assert_eq!(at_noon - at_midnight, 1 * Unit::Day / 2);
assert_eq!(at_midnight - at_noon, -1.days() / 2);
let delta_time = at_noon - at_midnight;
assert_eq!(format!("{}", delta_time), "12 h".to_string());
// And we can multiply durations by a scalar...
let delta2 = 2 * delta_time;
assert_eq!(format!("{}", delta2), "1 days".to_string());
// Or divide them by a scalar.
assert_eq!(format!("{}", delta2 / 2.0), "12 h".to_string());
// And of course, these comparisons account for differences in time scales
let at_midnight_utc = Epoch::from_gregorian_utc_at_midnight(2020, 11, 2);
let at_noon_tai = Epoch::from_gregorian_tai_at_noon(2020, 11, 2);
assert_eq!(format!("{}", at_noon_tai - at_midnight_utc), "11 h 59 min 23 s".to_string());
Timeunits and frequency units are trivially supported. Hifitime only supports up to nanosecond precision (but guarantees it for 64 millenia), so any duration less than one nanosecond is truncated.
use hifitime::{Epoch, Unit, Freq, Duration, TimeUnits};
// One can compare durations
assert!(10.seconds() > 5.seconds());
assert!(10.days() + 1.nanoseconds() > 10.days());
// Those durations are more precise than floating point since this is integer math in nanoseconds
let d: Duration = 1.0.hours() / 3 - 20.minutes();
assert!(d.abs() < Unit::Nanosecond);
assert_eq!(3 * 20.minutes(), Unit::Hour);
// And also frequencies but note that frequencies are converted to Durations!
// So the duration of that frequency is compared, hence the following:
assert!(10 * Freq::Hertz < 5 * Freq::Hertz);
assert!(4 * Freq::MegaHertz > 5 * Freq::MegaHertz);
// And asserts on the units themselves
assert!(Freq::GigaHertz < Freq::MegaHertz);
assert!(Unit::Second > Unit::Millisecond);
Iterating over times ("linspace" of epochs)
Finally, something which may come in very handy, line spaces between times with a given step.
use hifitime::{Epoch, Unit, TimeSeries};
let start = Epoch::from_gregorian_utc_at_midnight(2017, 1, 14);
let end = Epoch::from_gregorian_utc_at_noon(2017, 1, 14);
let step = 2 * Unit::Hour;
let time_series = TimeSeries::inclusive(start, end, step);
let mut cnt = 0;
for epoch in time_series {
println!("{}", epoch);
cnt += 1
}
// Check that there are indeed six two-hour periods in a half a day,
// including start and end times.
assert_eq!(cnt, 7)
Design
No software is perfect, so please report any issue or bugs on Github.
Duration
Under the hood, a Duration is represented as a 16 bit signed integer of centuries (i16
) and a 64 bit unsigned integer (u64
) of the nanoseconds past that century. The overflowing and underflowing of nanoseconds is handled by changing the number of centuries such that the nanoseconds number never represents more than one century (just over four centuries can be stored in 64 bits).
Advantages:
- Exact precision of a duration: using a floating point value would cause large durations (e.g. Julian Dates) to have less precision than smaller durations. Durations in hifitime have exactly one nanosecond of precision for 65,536 years.
- Skipping floating point operations allows this library to be used in embedded devices without a floating point unit.
- Duration arithmetics are exact, e.g. one third of an hour is exactly twenty minutes and not "0.33333 hours."
Disadvantages:
- Most astrodynamics applications require the computation of a duration in floating point values such as when querying an ephemeris. This design leads to an overhead of about 5.2 nanoseconds according to the benchmarks (
Duration to f64 seconds
benchmark). You may run the benchmarks withcargo bench
.
Printing and parsing
When Durations are printed, only the units whose value is non-zero is printed. For example, 5.hours() + 256.0.milliseconds() + 1.0.nanoseconds()
will be printed as "5 h 256 ms 1 ns".
use hifitime::{Duration, Unit, TimeUnits};
use core::str::FromStr;
assert_eq!(
format!(
"{}",
5.hours() + 256.0.milliseconds() + 1.0.nanoseconds()
),
"5 h 256 ms 1 ns"
);
assert_eq!(
format!(
"{}",
5.days() + 1.0.nanoseconds()
),
"5 days 1 ns"
);
assert_eq!(
Duration::from_str("5 h 256 ms 1 ns").unwrap(),
5 * Unit::Hour + 256 * Unit::Millisecond + Unit::Nanosecond
);
Epoch
The Epoch is simply a wrapper around a Duration. All epochs are stored in TAI duration with respect to 01 January 1900 at noon (the official TAI epoch). The choice of TAI meets the Standard of Fundamental Astronomy (SOFA) recommendation of opting for a glitch-free time scale (i.e. without discontinuities like leap seconds or non-uniform seconds like TDB).
Printing and parsing
Epochs can be formatted and parsed in the following time scales:
- UTC:
{epoch}
- TAI:
{epoch:x}
- TT:
{epoch:X}
- TDB:
{epoch:e}
- ET:
{epoch:E}
- UNIX:
{epoch:p}
- GPS:
{epoch:o}
use hifitime::{Epoch, TimeScale};
use core::str::FromStr;
let epoch = Epoch::from_gregorian_utc_hms(2022, 9, 6, 23, 24, 29);
assert_eq!(format!("{epoch}"), "2022-09-06T23:24:29 UTC");
assert_eq!(format!("{epoch:x}"), "2022-09-06T23:25:06 TAI");
assert_eq!(format!("{epoch:X}"), "2022-09-06T23:25:38.184000000 TT");
assert_eq!(format!("{epoch:E}"), "2022-09-06T23:25:38.182538909 ET");
assert_eq!(format!("{epoch:e}"), "2022-09-06T23:25:38.182541259 TDB");
assert_eq!(format!("{epoch:p}"), "1662506669"); // UNIX seconds
assert_eq!(format!("{epoch:o}"), "1346541887000000000"); // GPS nanoseconds
// RFC3339 parsing with time scales
assert_eq!(
Epoch::from_gregorian_utc_hms(1994, 11, 5, 13, 15, 30),
Epoch::from_str("1994-11-05T08:15:30-05:00").unwrap()
);
assert_eq!(
Epoch::from_gregorian_utc_hms(1994, 11, 5, 13, 15, 30),
Epoch::from_str("1994-11-05T13:15:30Z").unwrap()
);
// Same test with different time systems
// TAI
assert_eq!(
Epoch::from_gregorian_tai_hms(1994, 11, 5, 13, 15, 30),
Epoch::from_str("1994-11-05T08:15:30-05:00 TAI").unwrap()
);
assert_eq!(
Epoch::from_gregorian_tai_hms(1994, 11, 5, 13, 15, 30),
Epoch::from_str("1994-11-05T13:15:30Z TAI").unwrap()
);
// TDB
assert_eq!(
Epoch::from_gregorian_hms(1994, 11, 5, 13, 15, 30, TimeScale::TDB),
Epoch::from_str("1994-11-05T08:15:30-05:00 TDB").unwrap()
);
assert_eq!(
Epoch::from_gregorian_hms(1994, 11, 5, 13, 15, 30, TimeScale::TDB),
Epoch::from_str("1994-11-05T13:15:30Z TDB").unwrap()
);
Leap second support
Leap seconds allow TAI (the absolute time reference) and UTC (the civil time reference) to not drift too much. In short, UTC allows humans to see the sun at zenith at noon, whereas TAI does not worry about that. Leap seconds are introduced to allow for UTC to catch up with the absolute time reference of TAI. Specifically, UTC clocks are "stopped" for one second to make up for the accumulated difference between TAI and UTC. These leap seconds are announced several months in advance by IERS, cf. in the IETF leap second reference.
The "placement" of these leap seconds in the formatting of a UTC date is left up to the software: there is no common way to handle this. Some software prevents a second tick, i.e. at 23:59:59 the UTC clock will tick for two seconds (instead of one) before hoping to 00:00:00. Some software, like hifitime, allow UTC dates to be formatted as 23:59:60 on strictly the days when a leap second is inserted. For example, the date 2016-12-31 23:59:60 UTC
is a valid date in hifitime because a leap second was inserted on 01 Jan 2017.
Important
Prior to the first leap second, NAIF SPICE claims that there were nine seconds of difference between TAI and UTC: this is different from the Standard of Fundamental Astronomy (SOFA). SOFA's iauDat
function will return non-integer leap seconds from 1960 to 1972. It will return an error for dates prior to 1960. Hifitime only accounts for leap seconds announced by IERS in its computations: there is a ten (10) second jump between TAI and UTC on 01 January 1972. This allows the computation of UNIX time to be a specific offset of TAI in hifitime. However, the prehistoric (pre-1972) leap seconds as returned by SOFA are available in the leap_seconds()
method of an epoch if the iers_only
parameter is set to false.
Ephemeris Time vs Dynamic Barycentric Time (TDB)
In theory, as of January 2000, ET and TDB should now be identical. However, the NASA NAIF leap seconds files (e.g. naif00012.tls) use a simplified algorithm to compute the TDB:
Equation [4], which ignores small-period fluctuations, is accurate to about 0.000030 seconds.
In order to provide full interoperability with NAIF, hifitime uses the NAIF algorithm for "ephemeris time" and the ESA algorithm for "dynamical barycentric time." Hence, if exact NAIF behavior is needed, use all of the functions marked as et
instead of the tdb
functions, such as epoch.to_et_seconds()
instead of epoch.to_tdb_seconds()
.
Changelog
3.6.0
- Galileo System Time and BeiDou Time are now supported, huge thanks to @gwbres for all that work!
- Significant speed improvement in the initialization of Epochs from their Gregorian representation, thanks @conradludgate for #160.
- Epoch and Duration now have a
min
andmax
function which respectively returns a copy of the epoch/duration that is the smallest or the largest betweenself
andother
, cf. #164. - [Python] Duration and Epochs now support the operators
>
,>=
,<
,<=
,==
, and!=
. Epoch now supportsinit_from_gregorian
with a time scape, like in Rust. Epochs can also be subtracted from one another using thetimedelta
function, cf. #162. - TimeSeries can now be formatted in different time scales, cf. #163
3.5.0
- Epoch now store the time scale that they were defined in: this allows durations to be added in their respective time scales. For example, adding 36 hours to 1971-12-31 at noon when the Epoch is initialized in UTC will lead to a different epoch than adding that same duration to an epoch initialized at the same time in TAI (because the first leap second announced by IERS was on 1972-01-01), cf. the
test_add_durations_over_leap_seconds
test. - RFC3339 and ISO8601 fully supported for initialization of an Epoch, including the offset, e.g.
Epoch::from_str("1994-11-05T08:15:30-05:00")
, cf. #73. - Python package available on PyPI! To build the Python package, you must first install
maturin
and then build with thepython
feature flag. For example,maturin develop -F python && python
will build the Python package in debug mode and start a new shell where the package can be imported. - Fix bug when printing Duration::MIN (or any duration whose centuries are minimizing the number of centuries).
- TimeSeries can now be formatted
- Epoch can now be
ceil
-ed,floor
-ed, andround
-ed according to the time scale they were initialized in, cf. #145. - Epoch can now be initialized from Gregorian when specifying the time system:
from_gregorian
,from_gregorian_hms
,from_gregorian_at_noon
,from_gregorian_at_midnight
. - Fix bug in Duration when performing operations on durations very close to
Duration::MIN
(i.e. minus thirty-two centuries). - Duration parsing now supports multiple units in a string and does not use regular expressions. THis allows it to work with
no-std
. - Epoch parsing no longer requires
regex
. - Functions are not more idiomatic: all of the
as_*
functions becometo_*
andin_*
also becomesto_*
, cf. #155.
3.4.0
- Ephemeris Time and Dynamical Barycentric Time fixed to use the J2000 reference epoch instead of the J1900 reference epoch. This is a potentially breaking change if you relied on the previous one century error when converting from/to ET/TDB into/from UTC and storing the data as a string. There is no difference if the original representation was used.
- Ephemeris Time now strictly matches NAIF SPICE: the error between SPICE and hifitime is now zero nanoseconds. after the introduction of the first leap second. Prior to the first leap second, NAIF SPICE claims that there were nine seconds of difference between TAI and UTC: this is different from SOFA. Hifitime instead does not account for leap seconds in prehistoric (pre-1972) computations at all.
- The Standard of Fundamentals of Astronomy (SOFA) leap seconds from 1960 to 1972 are now available with the
leap_seconds() -> Option<f64>
function on an instance of Epoch. Importantly, no difference in the behavior of hifitime should be noticed here: the prehistoric leap seconds are ignored in all calculations in hifitime and only provided to meet the SOFA calculations. Epoch
andDuration
now have the C memory representation to allow for hifitime to be embedded in C more easily.Epoch
andDuration
can now be encoded or decoded as ASN1 DER with theasn1der
crate feature (disabled by default).
3.3.0
- Formal verification of the normalization operation on
Duration
, which in turn guarantees thatEpoch
operations cannot panic, cf. #127 - Fix
len
andsize_hint
forTimeSeries
, cf. #131, reported by @d3v-null, thanks for the find! Epoch
now implementsEq
andOrd
, cf. #133, thanks @mkolopanis for the PR!Epoch
can now be printed in different time systems with format modifiers, cf. #130- (minor)
as_utc_duration
inEpoch
is now public, cf. #129 - (minor) The whole crate now uses
num-traits
thereby skipping the explicit use oflibm
. Basically, operations onf64
look like normal Rust again, cf. #128 - (minor) Move the tests to their own folder to make it obvious that this is thoroughly tested
3.2.0
- Fix no-std implementation by using
libm
for non-core f64 operations - Add UNIX timestamp, thanks @mkolopanis
- Enums now derive
Eq
and some deriveOrd
(where relevant) #118 - Use const fn where possible and switch to references where possible #119
- Allow extracting the centuries and nanoseconds of a
Duration
andEpoch
, respectively with to_parts and to_tai_parts #122 - Add
ceil
,floor
,round
operations toEpoch
andDuration
3.1.0
- Add
#![no_std]
support - Add
to_parts
toDuration
to extract the centuries and nanoseconds of a duration - Allow building an
Epoch
from its duration and parts in TAI system - Add pure nanosecond (
u64
) constructor and getter for GPST since GPS based clocks will count in nanoseconds
Possibly breaking change
Errors::ParseError
no longer contains aString
but an enumParsingErrors
instead. This is considered possibly breaking because it would only break code in the cases where a datetime parsing or unit parsing was caught and handled (uncommon). Moreover, the output is stillDisplay
-able.
3.0.0
- Backend rewritten from TwoFloat to a struct of the centuries in
i16
and nanoseconds inu64
. Thanks to @pwnorbitals for proposing the idea in #107 and writing the proof of concept. This leads to at least a 2x speed up in most calculations, cf. this comment. - Fix GPS epoch, and addition of a helper functions in
Epoch
by @cjordan
2.2.3
- More deterministic
as_jde_tdb_days()
inEpoch
. In version 2.2.1, the ephemeris time and TDB days were identical down to machine precision. After a number of validation cases in the rotation equations of the IAU Earth to Earth Mean Equator J2000 frame, the new formulation was shown to lead to less rounding errors when requesting the days. These rounding errors prevented otherwise trivial test cases. However, it adds an error of 40.2 nanoseconds when initializing an Epoch with the days in ET and requesting the TDB days.
Note: this was originally published as 2.2.2 but I'd forgotten to update one of the tests with the 40.2 ns error.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Hashes for hifitime-3.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 34ab27fc96d0eb32649b4843eb9a46b2849ab42969ff095f9c86c72108b1989d |
|
MD5 | 3c43af1b76ac119cf957ddd89ee7a544 |
|
BLAKE2b-256 | 7aac456dfcc4a35463b8ec2c9f08019312c0e67f9b157d1b89895b3329d85019 |
Hashes for hifitime-3.6.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f849b7e3cf60a05bd1c220b9fb1c91ab0177cdfdbdf4fbdf3e14af79f389925f |
|
MD5 | ad9d0e064c6366efc0af9a5616a587b9 |
|
BLAKE2b-256 | 891dd607effcb5044ce7efb4845a265014818a47738fc92229ff8b502fe96f70 |
Hashes for hifitime-3.6.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ed38a1a064645de29a2a46e2cecb17bac55f0a96f527b2eed295cbefbd8d1a3a |
|
MD5 | 5d52245607842a38fdd619d42703f566 |
|
BLAKE2b-256 | d9075cdd3a60c8985195b7322d3245910c356d5395b73b0d948a15059c641a08 |
Hashes for hifitime-3.6.0-cp311-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5553aa637b06b40bdcf5018b55c6d967ec7ea60356306ba731fc781787368feb |
|
MD5 | 7391e30da55980fd6bb44ecf2aa6efc1 |
|
BLAKE2b-256 | 7270c1730a70ba2e81cce71e0675dff8e566c362fe8cefc93ff709205fc53247 |
Hashes for hifitime-3.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 853d38b3c53bb252ed3ef28011d19f51f0ac89e901e6db79c97a97028ca30ca6 |
|
MD5 | 5bc0857f3e71c545ce1367a4362b13b5 |
|
BLAKE2b-256 | 07f1b2452bb5b455e006cd9e88d9e7985fb8134887870c40c5dccb1beb3af4e2 |
Hashes for hifitime-3.6.0-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 29b492f34f7b7cb4d437d3fff91043ce2a012bcda3140a3f2bf6d38258e5e7b2 |
|
MD5 | 9494c6c38fb920bec41ad553615993fd |
|
BLAKE2b-256 | 09d9207d1ab35b5582ae40e879a5ec6efdfe77f79d329b91e63ab2731af51ff7 |
Hashes for hifitime-3.6.0-cp310-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6c6b4c85e7b88e61e142925726a422b410c8e1963dba2d2ba7711e790b576010 |
|
MD5 | b0de03aea8f30133726942a88cf16095 |
|
BLAKE2b-256 | 3c3001f26e3350c631ad287bf07b3e50c6cbfb151f84e665c32de794fc02b275 |
Hashes for hifitime-3.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2ca470b6529717deea2f9835dbe8d62ed380ddaa2f0486e51e4b26dca75ec296 |
|
MD5 | 4895d0d992ccb8f266fadfa9133d20e7 |
|
BLAKE2b-256 | 396a5b94ac7584b6f9fcc5b2b2bf466cf9c78afb8425817bc291557996056ba7 |
Hashes for hifitime-3.6.0-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | afe38e5f090c311b387ee9995362d3f3193c80bb2de3b5742b9a6257b3e10a11 |
|
MD5 | 7b33a2305def61bc553ac6cc4220e0cb |
|
BLAKE2b-256 | db1e06a652f30ffea4a9635c69f292bb19876a88ae928a45dc40878c52616f0b |
Hashes for hifitime-3.6.0-cp39-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9f75e329e5ba904b4b444fece0233874e25ae96ff525a7236093f30af1f5b768 |
|
MD5 | 75f7c82338a54deebc81a4b66fceb349 |
|
BLAKE2b-256 | 303ff17d756cc587808cde9db44ed30c3ab09cf68fefacdb5f3cd31f835edd4e |
Hashes for hifitime-3.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 55a9d1d75641e159fd36332226f4c0b49700ec5d7b24f248efeeb1cf76eca0bd |
|
MD5 | e8b7759965a1752d9c3df743fe86b563 |
|
BLAKE2b-256 | 23650ba9ba6a14a3393d5df2afe029ad36e36a79087305f1b41282ac69cd4eb2 |
Hashes for hifitime-3.6.0-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6ec5f18f3bf52cf3add4fbaaa7020ff91da15d983190d576d931a3418864be57 |
|
MD5 | fab53d9c307bfa38d3f6b445b2711766 |
|
BLAKE2b-256 | 81dab81ebf0cd509d75c1d0dfdba8654b3d934cd74e8ba8d3803a4807241254c |
Hashes for hifitime-3.6.0-cp38-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5a559e2427798c3dbbbea9691a08b1cc29b239702a53e5ccc591eb5f059c4dc6 |
|
MD5 | c297e8a7888480cb6bf1aeb100cf9c4e |
|
BLAKE2b-256 | c3c996fca5ac1959d8a739b6d8e840dc3a2b4ba7a3ad791d45fefb0443bc7352 |
Hashes for hifitime-3.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e3d346bd43bc49cc1ce789b06d86e818736914955e10d00b7c71cad360079bbe |
|
MD5 | 52428722495e54b2506c1e9f6a85b567 |
|
BLAKE2b-256 | 90fc6655517ef17ec358c59fc4aa1ea7c66510cae9bb19f3bd1d702bec08b7ad |
Hashes for hifitime-3.6.0-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 30645ee06600788e6c24b10638086b06be62fa43e696ea47859c321be59accd3 |
|
MD5 | f47904e43ef64386fcadac1c6a5d6d9c |
|
BLAKE2b-256 | 3a8829f446aa106ff96956e47bccf02b5ec028d2e920b5ee71e0d780577d1089 |
Hashes for hifitime-3.6.0-cp37-none-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5d731af9f898d548f1056d258276725ebd9e7a8eae0fee04e58125aa768e246f |
|
MD5 | 23d6eab0e33217d5f9248f559c658b5b |
|
BLAKE2b-256 | 9272279ea2bbcc2888db3a4281f8867a7a58a635eaa60e5fc873d3ea7b63e88d |
Hashes for hifitime-3.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2a8c8467dee704d20c8ca48592049491d551a73000c09f2a726e5aad51c73cf5 |
|
MD5 | f219361c0dc87034d5e995cceb2a507d |
|
BLAKE2b-256 | 8327f1b87c038f803ebc86c8085b44b4a2c1642d452321119d6af0b92e8bb365 |
Hashes for hifitime-3.6.0-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6503d1048ed067701aeed46dbee20fcdde86eb0303b2982fc7e085be6846a9ea |
|
MD5 | a9446bb7011fc56aed3f9c71867117ea |
|
BLAKE2b-256 | 20a73576edae28816092027de3cbb4c4314e7a18c4adb5def4bcdb23642d96ee |