pub mod arithmetic;
pub mod astronomy;
pub mod calendar;
pub mod civil_time;
pub mod comparisons;
pub mod constants;
pub mod conversions;
pub mod display_label;
pub mod exact;
pub mod formatting;
pub mod geodesy;
pub mod instant;
pub mod interplanetary;
pub mod intervals;
pub mod leap_seconds;
pub mod relativity;
pub mod scheduling;
pub mod serialization;
pub mod spacetime;
pub mod timezones;
pub mod types;
pub mod validation;
pub use display_label::{
compare_bd_labels, format_bd, format_bd_label, parse_bd, parse_bd_label,
BrightLabel, DEFAULT_BD_PRECISION,
};
pub use exact::ExactBrightDate;
pub use instant::BrightInstant;
pub use types::{BrightDateComponents, BrightDateOptions, BrightDuration, Precision};
use crate::constants::DEFAULT_PRECISION;
use crate::conversions::{
from_gps_time, from_iso, from_julian_date, from_modified_julian_date, from_unix_ms,
from_unix_seconds, to_date_time, to_gps_time, to_iso, to_julian_date,
to_modified_julian_date, to_unix_ms, to_unix_seconds, tai_utc_offset_seconds_at,
};
use crate::arithmetic::{
add, add_microdays, add_millidays, ceil_to_day, compare, difference,
absolute_difference, equals, floor_to_day, is_in_range, lerp, midpoint,
round_to_microday, round_to_milliday, subtract,
};
use crate::formatting::{
decompose, format_bright_date, format_duration, format_full, format_log,
format_prefixed, format_range, to_duration,
};
use chrono::{DateTime, Utc};
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, serde::Serialize, serde::Deserialize)]
pub struct BrightDate {
pub value: f64,
pub precision: Precision,
pub is_tai: bool,
}
impl BrightDate {
pub fn from_value(value: f64) -> Self {
Self {
value,
precision: DEFAULT_PRECISION,
is_tai: false,
}
}
pub fn from_value_with_options(value: f64, options: BrightDateOptions) -> Self {
Self {
value,
precision: options.precision.unwrap_or(DEFAULT_PRECISION),
is_tai: options.use_tai.unwrap_or(false),
}
}
pub fn now() -> Self {
let now_ms = Utc::now().timestamp_millis();
Self::from_value(from_unix_ms(now_ms as f64).unwrap_or(0.0))
}
pub fn from_date_time(dt: DateTime<Utc>) -> Self {
Self::from_value(from_unix_ms(dt.timestamp_millis() as f64).unwrap_or(0.0))
}
pub fn from_unix_ms(ms: f64) -> Result<Self, crate::types::BrightDateError> {
Ok(Self::from_value(from_unix_ms(ms)?))
}
pub fn from_unix_seconds(s: f64) -> Result<Self, crate::types::BrightDateError> {
Ok(Self::from_value(from_unix_seconds(s)?))
}
pub fn from_julian_date(jd: f64) -> Self {
Self::from_value(from_julian_date(jd))
}
pub fn from_modified_julian_date(mjd: f64) -> Self {
Self::from_value(from_modified_julian_date(mjd))
}
pub fn from_iso(s: &str) -> Result<Self, crate::types::BrightDateError> {
Ok(Self::from_value(from_iso(s)?))
}
pub fn from_gps_time(gps_week: u32, gps_seconds: f64) -> Self {
Self::from_value(from_gps_time(gps_week, gps_seconds))
}
pub fn epoch() -> Self {
Self::from_value(0.0)
}
pub fn to_date_time(&self) -> DateTime<Utc> {
to_date_time(self.value)
}
pub fn to_unix_ms(&self) -> f64 {
to_unix_ms(self.value)
}
pub fn to_unix_seconds(&self) -> f64 {
to_unix_seconds(self.value)
}
pub fn to_julian_date(&self) -> f64 {
to_julian_date(self.value)
}
pub fn to_modified_julian_date(&self) -> f64 {
to_modified_julian_date(self.value)
}
pub fn to_iso(&self) -> String {
to_iso(self.value)
}
pub fn to_gps_time(&self) -> (u32, f64) {
to_gps_time(self.value)
}
pub fn to_tai(&self) -> Self {
Self { value: self.value, precision: self.precision, is_tai: true }
}
pub fn to_utc(&self) -> Self {
Self { value: self.value, precision: self.precision, is_tai: false }
}
pub fn tai_utc_offset_seconds(&self) -> i32 {
tai_utc_offset_seconds_at(self.value)
}
pub fn add_days(&self, days: f64) -> Self {
Self { value: add(self.value, days), ..*self }
}
pub fn sub_days(&self, days: f64) -> Self {
Self { value: subtract(self.value, days), ..*self }
}
pub fn add_millidays(&self, md: f64) -> Self {
Self { value: add_millidays(self.value, md), ..*self }
}
pub fn add_microdays(&self, ud: f64) -> Self {
Self { value: add_microdays(self.value, ud), ..*self }
}
pub fn difference(&self, other: &Self) -> f64 {
difference(self.value, other.value)
}
pub fn absolute_difference(&self, other: &Self) -> f64 {
absolute_difference(self.value, other.value)
}
pub fn compare(&self, other: &Self) -> std::cmp::Ordering {
compare(self.value, other.value)
}
pub fn approx_eq(&self, other: &Self, tolerance: Option<f64>) -> bool {
equals(self.value, other.value, tolerance)
}
pub fn is_before(&self, other: &Self) -> bool {
self.value < other.value
}
pub fn is_after(&self, other: &Self) -> bool {
self.value > other.value
}
pub fn is_in_range(&self, start: &Self, end: &Self) -> bool {
is_in_range(self.value, start.value, end.value)
}
pub fn lerp(&self, other: &Self, t: f64) -> Self {
Self { value: lerp(self.value, other.value, t), ..*self }
}
pub fn midpoint(&self, other: &Self) -> Self {
Self { value: midpoint(self.value, other.value), ..*self }
}
pub fn floor_to_day(&self) -> Self {
Self { value: floor_to_day(self.value), ..*self }
}
pub fn ceil_to_day(&self) -> Self {
Self { value: ceil_to_day(self.value), ..*self }
}
pub fn round_to_milliday(&self) -> Self {
Self { value: round_to_milliday(self.value), ..*self }
}
pub fn round_to_microday(&self) -> Self {
Self { value: round_to_microday(self.value), ..*self }
}
pub fn format(&self) -> String {
format_bright_date(self.value, self.precision)
}
pub fn decompose(&self) -> BrightDateComponents {
decompose(self.value)
}
pub fn format_full(&self) -> crate::types::FormattedBrightDate {
format_full(self.value, self.precision)
}
pub fn to_log_string(&self) -> String {
format_log(self.value, self.precision)
}
pub fn to_prefixed_string(&self, prefix: Option<&str>) -> String {
format_prefixed(self.value, self.precision, prefix)
}
pub fn format_duration_to(&self, other: &Self) -> String {
let days = other.value - self.value;
format_duration(days)
}
pub fn duration_to(&self, other: &Self) -> BrightDuration {
to_duration(other.value - self.value)
}
pub fn format_range_to(&self, other: &Self) -> String {
format_range(self.value, other.value, self.precision)
}
}
impl std::fmt::Display for BrightDate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.format())
}
}
impl std::ops::Add<f64> for BrightDate {
type Output = Self;
fn add(self, rhs: f64) -> Self {
self.add_days(rhs)
}
}
impl std::ops::Sub<f64> for BrightDate {
type Output = Self;
fn sub(self, rhs: f64) -> Self {
self.sub_days(rhs)
}
}
impl std::ops::Sub<BrightDate> for BrightDate {
type Output = f64;
fn sub(self, rhs: BrightDate) -> f64 {
self.difference(&rhs)
}
}