// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/.
use chrono::{DateTime, Datelike, FixedOffset, TimeZone, Timelike};
/// A datetime type. /// /// Used to feed data to the `DatetimeMetric`. pubtype ChronoDatetime = DateTime<FixedOffset>;
/// Representation of a date, time and timezone. #[derive(Clone, PartialEq, Eq)] pubstruct Datetime { /// The year, e.g. 2021. pub year: i32, /// The month, 1=January. pub month: u32, /// The day of the month. pub day: u32, /// The hour. 0-23 pub hour: u32, /// The minute. 0-59. pub minute: u32, /// The second. 0-60. pub second: u32, /// The nanosecond part of the time. pub nanosecond: u32, /// The timezone offset from UTC in seconds. /// Negative for west, positive for east of UTC. pub offset_seconds: i32,
}
/// A datetime metric. /// /// Used to record an absolute date and time, such as the time the user first ran /// the application. #[derive(Clone, Debug)] pubstruct DatetimeMetric {
meta: Arc<CommonMetricDataInternal>,
time_unit: TimeUnit,
}
impl From<ChronoDatetime> for Datetime { fn from(dt: ChronoDatetime) -> Self { let date = dt.date(); let time = dt.time(); let tz = dt.timezone(); Self {
year: date.year(),
month: date.month(),
day: date.day(),
hour: time.hour(),
minute: time.minute(),
second: time.second(),
nanosecond: time.nanosecond(),
offset_seconds: tz.local_minus_utc(),
}
}
}
// IMPORTANT: // // When changing this implementation, make sure all the operations are // also declared in the related trait in `../traits/`. impl DatetimeMetric { /// Creates a new datetime metric. pubfn new(meta: CommonMetricData, time_unit: TimeUnit) -> Self { Self {
meta: Arc::new(meta.into()),
time_unit,
}
}
/// Sets the metric to a date/time including the timezone offset. /// /// # Arguments /// /// * `dt` - the optinal datetime to set this to. If missing the current date is used. pubfn set(&self, dt: Option<Datetime>) { let metric = self.clone(); crate::launch_with_glean(move |glean| {
metric.set_sync(glean, dt);
})
}
/// Sets the metric to a date/time which including the timezone offset synchronously. /// /// Use [`set`](Self::set) instead. #[doc(hidden)] pubfn set_sync(&self, glean: &Glean, value: Option<Datetime>) { if !self.should_record(glean) { return;
}
let value = match value {
None => local_now_with_offset(),
Some(dt) => { let timezone_offset = FixedOffset::east_opt(dt.offset_seconds); if timezone_offset.is_none() { let msg = format!( "Invalid timezone offset {}. Not recording.",
dt.offset_seconds
);
record_error(glean, &self.meta, ErrorType::InvalidValue, msg, None); return;
};
// The string version of the test function truncates using string // parsing. Unfortunately `parse_from_str` errors with `NotEnough` if we // try to truncate with `get_iso_time_string` and then parse it back // in a `Datetime`. So we need to truncate manually. let time = d.time(); match tu {
TimeUnit::Nanosecond => d.date().and_hms_nano_opt(
time.hour(),
time.minute(),
time.second(),
time.nanosecond(),
),
TimeUnit::Microsecond => {
eprintln!( "microseconds. nanoseconds={}, nanoseconds/1000={}",
time.nanosecond(),
time.nanosecond() / 1000
);
d.date().and_hms_nano_opt(
time.hour(),
time.minute(),
time.second(),
time.nanosecond() / 1000,
)
}
TimeUnit::Millisecond => d.date().and_hms_nano_opt(
time.hour(),
time.minute(),
time.second(),
time.nanosecond() / 1000000,
),
TimeUnit::Second => {
d.date()
.and_hms_nano_opt(time.hour(), time.minute(), time.second(), 0)
}
TimeUnit::Minute => d.date().and_hms_nano_opt(time.hour(), time.minute(), 0, 0),
TimeUnit::Hour => d.date().and_hms_nano_opt(time.hour(), 0, 0, 0),
TimeUnit::Day => d.date().and_hms_nano_opt(0, 0, 0, 0),
}
}
/// **Test-only API (exported for FFI purposes).** /// /// Gets the stored datetime value. /// /// The precision of this value is truncated to the `time_unit` precision. /// /// # Arguments /// /// * `ping_name` - the optional name of the ping to retrieve the metric /// for. Defaults to the first value in `send_in_pings`. /// /// # Returns /// /// The stored value or `None` if nothing stored. pubfn test_get_value(&self, ping_name: Option<String>) -> Option<Datetime> { crate::block_on_dispatcher(); crate::core::with_glean(|glean| { let dt = self.get_value(glean, ping_name.as_deref());
dt.map(Datetime::from)
})
}
/// **Test-only API (exported for FFI purposes).** /// /// Gets the stored datetime value, formatted as an ISO8601 string. /// /// The precision of this value is truncated to the `time_unit` precision. /// /// # Arguments /// /// * `ping_name` - the optional name of the ping to retrieve the metric /// for. Defaults to the first value in `send_in_pings`. /// /// # Returns /// /// The stored value or `None` if nothing stored. pubfn test_get_value_as_string(&self, ping_name: Option<String>) -> Option<String> { crate::block_on_dispatcher(); crate::core::with_glean(|glean| self.get_value_as_string(glean, ping_name))
}
/// **Test-only API** /// /// Gets the stored datetime value, formatted as an ISO8601 string. #[doc(hidden)] pubfn get_value_as_string(&self, glean: &Glean, ping_name: Option<String>) -> Option<String> { let value = self.get_value_inner(glean, ping_name.as_deref());
value.map(|(dt, tu)| get_iso_time_string(dt, tu))
}
/// **Exported for test purposes.** /// /// Gets the number of recorded errors for the given metric and error type. /// /// # Arguments /// /// * `error` - The type of error /// /// # Returns /// /// The number of errors reported. pubfn test_get_num_recorded_errors(&self, error: ErrorType) -> i32 { crate::block_on_dispatcher();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.