Read the time since the Unix epoch in nanoseconds. Will return 0 if the system-reported time is somehow before the Unix epoch.
Uses SystemTime on native platforms and Date in WASM.
9#[must_use] 10pub fn current_time_nanos() -> u128 { 11 cfg_select! { 12 target_arch = "wasm32" => { 13 let current_time_ms = js_sys::Date::now(); 14 (current_time_ms * 1_000_000.0) as u128 15 } 16 _ => { 17 use std::time::SystemTime; 18 19 SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap_or_default().as_nanos() 20 } 21 } 22}
Sleep until at least the specified time. Returns the current time in nanoseconds after sleeping.
This implementation will try to sleep until 1ms before the target time and then it will busy
wait until the target time. This is to work around the fact that thread::sleep() only guarantees
that it will sleep at least the specified duration, and it could sleep longer. Sleeping longer
seems to be particularly common on Windows.
If the current time is already past the target time, this function will return immediately without sleeping.
33#[inline] 34#[allow(clippy::must_use_candidate)] 35pub fn sleep_until(time_nanos: u128) -> u128 { 36 loop { 37 let now = current_time_nanos(); 38 if now >= time_nanos { 39 return now; 40 } 41 42 let duration = Duration::from_nanos((time_nanos - now) as u64); 43 if duration > Duration::from_millis(1) { 44 thread::sleep(duration - Duration::from_millis(1)); 45 } 46 } 47}
Determine the number of days in the given month+year.
Leap years are accounted for, but only in that February is assumed to be 29 days in every 4th year. Other leap year rules are intentionally not applied.
53#[must_use] 54pub fn days_in_month(month: u8, year: u8) -> u8 { 55 match month { 56 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31, 57 4 | 6 | 9 | 11 => 30, 58 2 => { 59 // This is not strictly accurate (it doesn't account for not divisible by 100 or divisible 60 // by 400) but it matches what the RTC chips do 61 if year.is_multiple_of(4) { 29 } else { 28 } 62 } 63 _ => { 64 log::error!("Invalid month: {month}, defaulting to 31 days in month"); 65 31 66 } 67 } 68}
Determine the weekday of a given date. Day and month should both start at 1, not 0.
71#[must_use] 72pub fn day_of_week(day: u8, month: u8, year: u16) -> Weekday { 73 match Date::from_calendar_date(year.into(), convert_month(month), day) { 74 Ok(date) => date.weekday(), 75 Err(err) => { 76 log::error!("Invalid date (day={day}, month={month}, year={year}): {err}"); 77 Weekday::Sunday 78 } 79 } 80}
82fn convert_month(month: u8) -> Month { 83 use Month::*; 84 85 match month { 86 1 => January, 87 2 => February, 88 3 => March, 89 4 => April, 90 5 => May, 91 6 => June, 92 7 => July, 93 8 => August, 94 9 => September, 95 10 => October, 96 11 => November, 97 12 => December, 98 _ => { 99 log::error!("Invalid month: {month} defaulting to January"); 100 January 101 } 102 } 103}