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}