summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrendan Coles <bcoles@gmail.com>2021-01-07 15:58:57 +0000
committerAndreas Kling <kling@serenityos.org>2021-01-08 09:42:43 +0100
commitd0a9954f0e8393c0eb68ca53bd246ed10d137361 (patch)
treeb6327cf4c553c8cc93cf3817a550986085b55874
parentfb9eb2054461fd5622e6a80c66af265fba8f62be (diff)
downloadserenity-d0a9954f0e8393c0eb68ca53bd246ed10d137361.zip
Userland: Add ddate utility
Today is Boomtime, day 7 of Chaos, in the YOLD 3187
-rw-r--r--Base/usr/share/man/man1/ddate.md20
-rw-r--r--Userland/ddate.cpp132
2 files changed, 152 insertions, 0 deletions
diff --git a/Base/usr/share/man/man1/ddate.md b/Base/usr/share/man/man1/ddate.md
new file mode 100644
index 0000000000..a8fdceab88
--- /dev/null
+++ b/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
+```
diff --git a/Userland/ddate.cpp b/Userland/ddate.cpp
new file mode 100644
index 0000000000..763a5a3493
--- /dev/null
+++ b/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;
+}