浏览代码

Userland: Add ddate utility

Today is Boomtime, day 7 of Chaos, in the YOLD 3187
Brendan Coles 4 年之前
父节点
当前提交
d0a9954f0e
共有 2 个文件被更改,包括 152 次插入0 次删除
  1. 20 0
      Base/usr/share/man/man1/ddate.md
  2. 132 0
      Userland/ddate.cpp

+ 20 - 0
Base/usr/share/man/man1/ddate.md

@@ -0,0 +1,20 @@
+## Name
+
+ddate - prints the current date in Discordian date format.
+
+## Synopsis
+
+```**sh
+$ ddate
+```
+
+## Description
+
+ddate prints the current date in Discordian date format.
+
+## Examples
+
+```sh
+$ ddate # Thu 07 Jan 2021
+Today is Boomtime, day 7 of Chaos, in the YOLD 3187
+```

+ 132 - 0
Userland/ddate.cpp

@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2021, the SerenityOS developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/String.h>
+#include <LibCore/DateTime.h>
+#include <stdio.h>
+
+class DiscordianDate {
+public:
+    explicit DiscordianDate(Core::DateTime date)
+    {
+        m_gregorian_date = date;
+        m_yold = date.year() + 1166;
+
+        uint16_t day = day_of_yold() + 1;
+        if (is_leap_year() && day > m_st_tibs_day_of_yold)
+            --day;
+
+        m_day_of_week = day_of_week_from_day_of_yold(day);
+        m_season = season_from_day_of_yold(day);
+        m_date = date_from_day_of_yold(day);
+    }
+
+    const char* day_of_week() { return m_day_of_week.characters(); };
+    const char* season() { return m_season.characters(); };
+    uint16_t year() { return yold(); };
+    uint16_t yold() { return m_yold; };
+    uint16_t day_of_year() { return day_of_yold(); };
+    uint16_t day_of_yold() { return m_gregorian_date.day_of_year(); };
+    bool is_leap_year() { return m_gregorian_date.is_leap_year(); };
+    bool is_st_tibs_day() { return (is_leap_year() && (day_of_yold() + 1) == m_st_tibs_day_of_yold); };
+
+    String to_string()
+    {
+        if (is_st_tibs_day())
+            return String::formatted("St. Tib's Day, in the YOLD {}", m_yold);
+        return String::formatted("{}, day {} of {}, in the YOLD {}", m_day_of_week, m_date, m_season, m_yold);
+    }
+
+private:
+    static const int m_days_in_week = 5;
+    static const int m_days_in_season = 73;
+    static const int m_st_tibs_day_of_yold = 60;
+    Core::DateTime m_gregorian_date;
+    String m_day_of_week;
+    String m_season;
+    int m_date;
+    uint64_t m_yold; // 64-bit for use after X-Day in the YOLD 8661
+
+    int date_from_day_of_yold(uint16_t day)
+    {
+        return (day % m_days_in_season == 0 ? m_days_in_season : day % m_days_in_season);
+    }
+
+    const char* day_of_week_from_day_of_yold(uint16_t day)
+    {
+        if (is_st_tibs_day())
+            return nullptr;
+
+        switch ((day % m_days_in_week) == 0 ? m_days_in_week : (day % m_days_in_week)) {
+        case 1:
+            return "Sweetmorn";
+        case 2:
+            return "Boomtime";
+        case 3:
+            return "Pungenday";
+        case 4:
+            return "Prickle-Prickle";
+        case 5:
+            return "Setting Orange";
+        default:
+            return nullptr;
+        }
+    }
+
+    const char* season_from_day_of_yold(uint16_t day)
+    {
+        if (is_st_tibs_day())
+            return nullptr;
+
+        switch (((day % m_days_in_season) == 0 ? day - 1 : day) / m_days_in_season) {
+        case 0:
+            return "Chaos";
+        case 1:
+            return "Discord";
+        case 2:
+            return "Confusion";
+        case 3:
+            return "Bureaucracy";
+        case 4:
+            return "The Aftermath";
+        default:
+            return nullptr;
+        }
+    }
+};
+
+int main([[maybe_unused]] int argc, [[maybe_unused]] char** argv)
+{
+    if (pledge("stdio", nullptr) < 0) {
+        perror("pledge");
+        return 1;
+    }
+
+    auto date = Core::DateTime::from_timestamp(time(nullptr));
+    printf("Today is %s\n", DiscordianDate(date).to_string().characters());
+
+    return 0;
+}