1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
use chrono::{DateTime,Utc};
const EORZEA_CONSTANT: f64 = 3600.0 / 175.0;
// General conversion rates
pub const EORZEA_SECONDS_PER_MINUTE: f64 = 60.0;
pub const EORZEA_SECONDS_PER_HOUR: f64 = 60.0 * EORZEA_SECONDS_PER_MINUTE;
pub const EORZEA_SECONDS_PER_SUN: f64 = 24.0 * EORZEA_SECONDS_PER_HOUR;
pub const EORZEA_SECONDS_PER_WEEK: f64 = 8.0 * EORZEA_SECONDS_PER_SUN;
pub const EORZEA_SECONDS_PER_MOON: f64 = 4.0 * EORZEA_SECONDS_PER_WEEK;
pub const EORZEA_SECONDS_PER_YEAR: f64 = 12.0 * EORZEA_SECONDS_PER_MOON;
pub const EORZEA_THE_TWELVE: [&str; 12] = [
"Halone",
"Menphina",
"Thaliak",
"Nymeia",
"Llymlaen",
"Oschon",
"Byregot",
"Rhalgr",
"Azeyma",
"Nald'thal",
"Nophica",
"Althyk",
];
pub const EORZEA_MOON_PHASES: [&str; 8] = [
"New Moon",
"Waxing Crescent",
"Waxing Half Moon",
"Waxing Gibbous",
"Full Moon",
"Waning Gibbous",
"Waning Half Moon",
"Waning Crescent",
];
pub const EORZEA_MOON_CYCLE_PREFIX: [&str; 6] = [
"First", "Second", "Third", "Fourth", "Fifth", "Sixth"
];
#[derive(Debug)]
pub struct EorzeanTime {
pub years: u64,
pub moons: u64,
pub weeks: u64,
pub suns: u64,
pub bells: u64,
pub minutes: u64,
pub seconds: u64,
}
#[derive(Debug)]
pub struct EorzeanDate {
pub guardian: String,
pub phase: String,
pub moon: String,
pub years: u64,
pub suns: u64,
pub bells: u64,
pub minutes: u64,
}
/// Handles i64 and DateTime<Utc> types
pub trait ToUnixTimestamp {
/// Converts the implementing type to a Unix timestamp.
///
/// # Returns
///
/// An `i64` representing the Unix timestamp
fn to_unix_timestamp(&self) -> i64;
}
impl ToUnixTimestamp for i64 {
/// Returns the `i64` value as the Unix timestamp
fn to_unix_timestamp(&self) -> i64 {
*self
}
}
impl ToUnixTimestamp for DateTime<Utc> {
/// Converts `DateTime<Utc>` to a Unix timestamp in milliseconds
fn to_unix_timestamp(&self) -> i64 {
self.timestamp_millis()
}
}
/// Calculates the Eorzean time given a Unix timestamp
///
/// # Arguments
/// - `input_time` - A type that implements the `ToUnixTimestamp` trait (i64 or chrono::DateTime<Utc>)
///
/// # Returns
/// - An EorzeanDate struct representing the Eorzean time equivalent of the input time
pub fn convert_to_eorzean_date<T: ToUnixTimestamp>(input_time: T) -> EorzeanDate {
let local_epoch = input_time.to_unix_timestamp();
let epoch = local_epoch as f64 * EORZEA_CONSTANT;
let minutes = (epoch / (1000.0 * EORZEA_SECONDS_PER_MINUTE)) % EORZEA_SECONDS_PER_MINUTE;
let bells = (epoch / (1000.0 * EORZEA_SECONDS_PER_HOUR)) % 24.0;
let total_suns = (epoch / (1000.0 * EORZEA_SECONDS_PER_SUN)) as u64;
let year = total_suns / (32 * 12);
let moon_idx = (total_suns / 32) % 12 + 1;
let mut moon_str = EORZEA_MOON_CYCLE_PREFIX[(moon_idx / 2) as usize].to_string();
if moon_idx % 2 == 0 {
moon_str.push_str(" Umbral Moon");
} else {
moon_str.push_str(" Astral Moon");
}
let sun = total_suns % 32 + 1;
let guardian = EORZEA_THE_TWELVE[(moon_idx - 1) as usize].to_string();
let moon_phase = EORZEA_MOON_PHASES[(sun / 4) as usize].to_string();
EorzeanDate {
guardian: guardian,
phase: moon_phase,
moon: moon_str,
years: year as u64,
suns: sun as u64,
bells: bells as u64,
minutes: minutes as u64,
}
}
/// Converts a Unix timestamp to Eorzean time
/// A much simpler function to quickly get the current Eorzean time
///
/// # Arguments
/// - `input_time` - A type that implements the `ToUnixTimestamp` trait (i64 or chrono::DateTime<Utc>)
///
/// # Returns
/// - A tuple containing the bells and minutes of the Eorzean time equivalent of the input time
pub fn convert_to_eorzean_time<T: ToUnixTimestamp>(input_time: T) -> (u8, u8) {
let local_epoch = input_time.to_unix_timestamp();
let epoch = local_epoch as f64 * EORZEA_CONSTANT;
let minutes = (epoch / (1000.0 * 60.0)) % 60.0;
let bells = (epoch / (1000.0 * 60.0 * 60.0)) % 24.0;
(bells as u8, minutes as u8)
}
/// Converts seconds to an EorzeanTime struct
///
/// # Arguments
/// - `seconds` - A `f64` representing the number of seconds to convert
///
/// # Returns
/// - An `EorzeanTime` struct representing the Eorzean time equivalent of the input seconds
pub fn convert_earth_seconds_to_eorzean_duration(seconds: f64) -> EorzeanTime {
let eorzean_seconds = seconds * 1.0/0.0486;
let years = (eorzean_seconds / EORZEA_SECONDS_PER_YEAR) as u64;
let remaining_seconds = eorzean_seconds % EORZEA_SECONDS_PER_YEAR;
let months = (remaining_seconds / EORZEA_SECONDS_PER_MOON) as u64;
let remaining_seconds = remaining_seconds % EORZEA_SECONDS_PER_MOON;
let weeks = (remaining_seconds / EORZEA_SECONDS_PER_WEEK) as u64;
let remaining_seconds = remaining_seconds % EORZEA_SECONDS_PER_WEEK;
let days = (remaining_seconds / EORZEA_SECONDS_PER_SUN) as u64;
let remaining_seconds = remaining_seconds % EORZEA_SECONDS_PER_SUN;
let bells = (remaining_seconds / EORZEA_SECONDS_PER_HOUR) as u64;
let remaining_seconds = remaining_seconds % EORZEA_SECONDS_PER_HOUR;
let minutes = (remaining_seconds / EORZEA_SECONDS_PER_MINUTE) as u64;
let seconds = remaining_seconds % EORZEA_SECONDS_PER_MINUTE;
EorzeanTime {
years,
moons: months,
weeks,
suns: days,
bells,
minutes,
seconds: seconds as u64,
}
}
/// Converts an EorzeanDuration to Earth seconds
///
/// # Arguments
/// - `eorzean_duration` - An `EorzeanTime` struct representing the Eorzean time equivalent of the input seconds
///
/// # Returns
/// - A `i64` representing the number of Earth seconds corresponding to the Eorzean duration
pub fn convert_eorzean_duration_to_earth_seconds(eorzean_duration: EorzeanTime) -> f64 {
let total_seconds = eorzean_duration.years as f64 * EORZEA_SECONDS_PER_YEAR +
eorzean_duration.moons as f64 * EORZEA_SECONDS_PER_MOON +
eorzean_duration.weeks as f64 * EORZEA_SECONDS_PER_WEEK +
eorzean_duration.suns as f64 * EORZEA_SECONDS_PER_SUN +
eorzean_duration.bells as f64 * EORZEA_SECONDS_PER_HOUR +
eorzean_duration.minutes as f64 * EORZEA_SECONDS_PER_MINUTE +
eorzean_duration.seconds as f64;
total_seconds * (35.0/720.0)
}
|