doom_2038/
lib.rs

1use std::thread;
2use std::time::{Duration, SystemTime, UNIX_EPOCH};
3
4/// The Unix timestamp for the Year 2038 problem:
5/// 2038-01-19 03:14:07 UTC. This timestamp represents
6/// the maximum value for a 32-bit signed integer.
7///
8/// # Examples
9///
10/// ```
11/// use doom_2038::DOOM_TS;
12///
13/// let u32_limit = DOOM_TS;
14/// assert_eq!(u32_limit, 2_147_483_647);
15/// ```
16pub const DOOM_TS: u64 = 2_147_483_647;
17
18/// Amount of seconds in a minute
19pub const SECONDS_IN_MINUTE: u64 = 60;
20/// Amount of seconds in an hour
21pub const SECONDS_IN_HOUR: u64 = 3600;
22/// Amount of seconds in a day
23pub const SECONDS_IN_DAY: u64 = 86_400; // 24 * 60 * 60
24/// Amount of seconds in a year
25pub const SECONDS_IN_YEAR: u64 = 31_536_000; // 365 * 24 * 60 * 60
26
27/// Calculates the time left until the Year 2038 problem occurs,
28/// returning it as a `Duration`.
29///
30/// This function computes the difference between the current time
31/// and the DOOM_TS constant, which marks the limit of a 32-bit
32/// unsigned integer. If the current time is past the doom timestamp,
33/// this will return a `Duration` of zero.
34///
35/// # Returns
36///
37/// A `Duration` representing the time remaining until the Year 2038 problem.
38///
39/// # Examples
40///
41/// ```
42/// use doom_2038::time_left;
43///
44/// let duration_left = time_left();
45/// println!("Time left until 2038 problem: {:?}", duration_left);
46/// ```
47pub fn time_left() -> Duration {
48    let now = SystemTime::now()
49        .duration_since(UNIX_EPOCH)
50        .expect("Time went backwards");
51    Duration::from_secs(DOOM_TS.saturating_sub(now.as_secs()))
52}
53
54/// Displays the time left until whatever in a
55/// human-readable format.
56///
57/// # Parameters
58///
59/// - `duration`: A `Duration` indicating the time left.
60///
61/// # Examples
62///
63/// ```
64/// use std::time::Duration;
65/// use doom_2038::print_time_left;
66///
67/// let remaining_time = Duration::new(5000, 0); // Example duration
68/// print_time_left(remaining_time);
69/// ```
70pub fn print_time_left(duration: Duration) {
71    let total_seconds = duration.as_secs();
72
73    if total_seconds >= SECONDS_IN_YEAR {
74        let years = total_seconds / SECONDS_IN_YEAR;
75        let remaining_seconds = total_seconds % SECONDS_IN_YEAR;
76
77        let days = remaining_seconds / SECONDS_IN_DAY;
78        let remaining_seconds = remaining_seconds % SECONDS_IN_DAY;
79
80        let hours = remaining_seconds / SECONDS_IN_HOUR;
81        let remaining_seconds = remaining_seconds % SECONDS_IN_HOUR;
82
83        let minutes = remaining_seconds / SECONDS_IN_MINUTE;
84        let seconds = remaining_seconds % SECONDS_IN_MINUTE;
85
86        println!(
87            "{} years, {} days, {} hours, {} minutes, {} seconds",
88            years, days, hours, minutes, seconds
89        );
90    } else if total_seconds >= SECONDS_IN_DAY {
91        let days = total_seconds / SECONDS_IN_DAY;
92        let remaining_seconds = total_seconds % SECONDS_IN_DAY;
93
94        let hours = remaining_seconds / SECONDS_IN_HOUR;
95        let remaining_seconds = remaining_seconds % SECONDS_IN_HOUR;
96
97        let minutes = remaining_seconds / SECONDS_IN_MINUTE;
98        let seconds = remaining_seconds % SECONDS_IN_MINUTE;
99
100        println!(
101            "{} days, {} hours, {} minutes, {} seconds",
102            days, hours, minutes, seconds
103        );
104    } else if total_seconds >= SECONDS_IN_HOUR {
105        let hours = total_seconds / SECONDS_IN_HOUR;
106        let remaining_seconds = total_seconds % SECONDS_IN_HOUR;
107
108        let minutes = remaining_seconds / SECONDS_IN_MINUTE;
109        let seconds = remaining_seconds % SECONDS_IN_MINUTE;
110
111        println!("{} hours, {} minutes, {} seconds", hours, minutes, seconds);
112    } else if total_seconds >= SECONDS_IN_MINUTE {
113        let minutes = total_seconds / SECONDS_IN_MINUTE;
114        let seconds = total_seconds % SECONDS_IN_MINUTE;
115
116        println!("{} minutes, {} seconds", minutes, seconds);
117    } else {
118        println!("{} seconds", total_seconds);
119    }
120}
121
122/// Runs the doom countdown either continuously or just once,
123/// based on the `countdown` flag.
124///
125/// If `countdown` is set to true, the function enters a loop
126/// that refreshes and prints the time left every second.
127/// If false, it simply prints the time left once.
128///
129/// # Parameters
130///
131/// - `countdown`: A boolean that determines whether to run the countdown continuously or just once.
132///
133/// # Examples
134///
135/// ```
136/// use doom_2038::doom;
137///
138/// // To run the countdown continuously:
139/// // doom(true); // Uncomment to run
140///
141/// // To print the time left once:
142/// doom(false);
143/// ```
144pub fn doom(countdown: bool) {
145    if countdown {
146        loop {
147            print_time_left(time_left());
148            thread::sleep(Duration::from_secs(1));
149        }
150    } else {
151        print_time_left(time_left());
152    }
153}