build_info_build/build_script_options/
timestamp.rs1use chrono::{DateTime, TimeZone, Utc};
2
3impl crate::BuildScriptOptions {
4 pub fn build_timestamp(mut self, timestamp: DateTime<Utc>) -> Self {
10 self.timestamp = Some(timestamp);
11 self
12 }
13
14 pub fn build_timestamp_as_nanos(mut self, nanos: i64) -> Self {
20 self.timestamp = Some(Utc.timestamp_nanos(nanos));
21 self
22 }
23}
24
25pub(crate) fn get_timestamp() -> DateTime<Utc> {
26 get_timestamp_internal(std::env::var("SOURCE_DATE_EPOCH").ok())
27}
28
29fn get_timestamp_internal(epoch: Option<String>) -> DateTime<Utc> {
30 if let Some(epoch) = epoch {
32 let epoch: i64 = epoch.parse().expect("Could not parse SOURCE_DATE_EPOCH");
33 match Utc.timestamp_opt(epoch, 0) {
34 chrono::LocalResult::None => panic!("Invalid SOURCE_DATE_EPOCH: {epoch}"),
35 chrono::LocalResult::Single(timestamp) => timestamp,
36 chrono::LocalResult::Ambiguous(min, max) => {
37 panic!("Ambiguous epoch: {epoch} could refer to {min} or {max}. This should never occur for UTC!")
38 }
39 }
40 } else {
41 Utc::now()
42 }
43}
44
45#[cfg(test)]
46mod test {
47 use pretty_assertions::assert_eq;
48
49 use super::*;
50
51 #[test]
52 fn get_current_timestamp() {
53 let past = Utc.timestamp_opt(1591113000, 0).single().unwrap();
54 let now = get_timestamp_internal(None);
55 let future = Utc.timestamp_opt(32503680000, 0).single().unwrap();
56 assert!(past < now);
57 assert!(now < future);
58 }
59
60 #[test]
61 fn get_fixed_timestamp() {
62 let epoch = 1591113000;
63 assert_eq!(
64 get_timestamp_internal(Some(epoch.to_string())),
65 Utc.timestamp_opt(epoch, 0).single().unwrap()
66 );
67 }
68}