--- /dev/null
+/*
+ * Copyright (c) 2020 Tilman Sauerbeck (tilman at code-monkey de)
+ *
+ * Time::from_unix_time() adapted from musl's __secs_to_tm() which is
+ * Copyright © 2005-2020 Rich Felker, et al.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+pub struct Time {
+ seconds: i32,
+ minutes: i32,
+ hours: i32,
+ day: i32,
+ month: i32,
+ year: i32,
+}
+
+// 2000-03-01 (mod 400 year, immediately after feb29
+const LEAPOCH: i32 = (946684800 + 86400 * (31 + 29));
+
+const DAYS_PER_400Y: i32 = (365 * 400 + 97);
+const DAYS_PER_100Y: i32 = (365 * 100 + 24);
+const DAYS_PER_4Y : i32 = (365 * 4 + 1);
+
+const DAYS_IN_MONTH : [i32; 12] = [ 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29 ];
+
+impl Time {
+ pub fn from_unix_time(u: u32) -> Option<Time> {
+ let t = u as i32;
+
+ let secs = t - LEAPOCH;
+ let mut days = secs / 86400;
+ let mut remsecs = secs % 86400;
+
+ if remsecs < 0 {
+ remsecs += 86400;
+ days -= 1;
+ }
+
+ let mut qc_cycles = days / DAYS_PER_400Y;
+ let mut remdays = days % DAYS_PER_400Y;
+
+ if remdays < 0 {
+ remdays += DAYS_PER_400Y;
+ qc_cycles -= 1;
+ }
+
+ let mut c_cycles = remdays / DAYS_PER_100Y;
+
+ if c_cycles == 4 {
+ c_cycles -= 1;
+ }
+
+ remdays -= c_cycles * DAYS_PER_100Y;
+
+ let mut q_cycles = remdays / DAYS_PER_4Y;
+
+ if q_cycles == 25 {
+ q_cycles -= 1;
+ }
+
+ remdays -= q_cycles * DAYS_PER_4Y;
+
+ let mut remyears = remdays / 365;
+
+ if remyears == 4 {
+ remyears -= 1;
+ }
+
+ remdays -= remyears * 365;
+
+ let mut years =
+ remyears + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles;
+
+ let mut months = 0;
+
+ while remdays >= DAYS_IN_MONTH[months as usize] {
+ remdays -= DAYS_IN_MONTH[months as usize];
+ months += 1;
+ }
+
+ if months >= 10 {
+ months -= 12;
+ years += 1;
+ }
+
+ if years + 100 > i32::max_value() || years + 100 < i32::min_value() {
+ None
+ } else {
+ Some(Time {
+ year: years + 100,
+ month: months + 2,
+ day: remdays + 1,
+ hours: remsecs / 3600,
+ minutes: remsecs / 60 % 60,
+ seconds: remsecs % 60,
+ })
+ }
+ }
+}