9
+ − 1 #include "core/date.h"
+ − 2 #include "core/json.h"
+ − 3 #include <QDate>
+ − 4 #include <cstdint>
+ − 5 #include <tuple>
+ − 6
+ − 7 /* An implementation of AniList's "fuzzy date" */
+ − 8
+ − 9 #define MIN(A, B) \
+ − 10 ({ \
+ − 11 __typeof__(A) __a = (A); \
+ − 12 __typeof__(B) __b = (B); \
+ − 13 __a < __b ? __a : __b; \
+ − 14 })
+ − 15 #define MAX(A, B) \
+ − 16 ({ \
+ − 17 __typeof__(A) __a = (A); \
+ − 18 __typeof__(B) __b = (B); \
+ − 19 __a < __b ? __b : __a; \
+ − 20 })
+ − 21
+ − 22 #define CLAMP(x, low, high) \
+ − 23 ({ \
+ − 24 __typeof__(x) __x = (x); \
+ − 25 __typeof__(low) __low = (low); \
+ − 26 __typeof__(high) __high = (high); \
+ − 27 __x > __high ? __high : (__x < __low ? __low : __x); \
+ − 28 })
+ − 29
+ − 30 Date::Date() {
+ − 31 }
+ − 32
+ − 33 Date::Date(int32_t y) {
11
+ − 34 SetYear(y);
9
+ − 35 }
+ − 36
+ − 37 Date::Date(int32_t y, int8_t m, int8_t d) {
11
+ − 38 SetYear(y);
+ − 39 SetMonth(m);
+ − 40 SetDay(d);
9
+ − 41 }
+ − 42
+ − 43 void Date::VoidYear() {
+ − 44 year.reset();
+ − 45 }
+ − 46
+ − 47 void Date::VoidMonth() {
+ − 48 month.reset();
+ − 49 }
+ − 50
+ − 51 void Date::VoidDay() {
+ − 52 day.reset();
+ − 53 }
+ − 54
+ − 55 void Date::SetYear(int32_t y) {
11
+ − 56 year.reset(new int32_t(MAX(0, y)));
9
+ − 57 }
+ − 58
+ − 59 void Date::SetMonth(int8_t m) {
11
+ − 60 month.reset(new int8_t(CLAMP(m, 1, 12)));
9
+ − 61 }
+ − 62
+ − 63 void Date::SetDay(int8_t d) {
11
+ − 64 day.reset(new int8_t(CLAMP(d, 1, 31)));
9
+ − 65 }
+ − 66
+ − 67 int32_t Date::GetYear() const {
+ − 68 int32_t* ptr = year.get();
+ − 69 if (ptr != nullptr)
+ − 70 return *year;
+ − 71 return -1;
+ − 72 }
+ − 73
+ − 74 int8_t Date::GetMonth() const {
+ − 75 int8_t* ptr = month.get();
+ − 76 if (ptr != nullptr)
+ − 77 return *month;
+ − 78 return -1;
+ − 79 }
+ − 80
+ − 81 int8_t Date::GetDay() const {
+ − 82 int8_t* ptr = day.get();
+ − 83 if (ptr != nullptr)
+ − 84 return *day;
+ − 85 return -1;
+ − 86 }
+ − 87
+ − 88 bool Date::operator<(const Date& other) const {
+ − 89 int o_y = other.GetYear(), o_m = other.GetMonth(), o_d = other.GetDay();
+ − 90 return std::tie(*year, *month, *day) < std::tie(o_y, o_m, o_d);
+ − 91 }
+ − 92
+ − 93 bool Date::operator>(const Date& other) const {
+ − 94 return other < (*this);
+ − 95 }
+ − 96
+ − 97 bool Date::operator<=(const Date& other) const {
+ − 98 return !((*this) > other);
+ − 99 }
+ − 100
+ − 101 bool Date::operator>=(const Date& other) const {
+ − 102 return !((*this) < other);
+ − 103 }
+ − 104
+ − 105 QDate Date::GetAsQDate() const {
10
+ − 106 /* QDates don't (yet) support "missing" values */
+ − 107 if (year.get() && month.get() && day.get())
+ − 108 return QDate(*year, *month, *day);
15
+ − 109 else
+ − 110 return QDate();
9
+ − 111 }
+ − 112
+ − 113 nlohmann::json Date::GetAsAniListJson() const {
+ − 114 nlohmann::json result;
+ − 115 if (year.get())
+ − 116 result.insert(result.end(), {"year", *year});
+ − 117 else
+ − 118 result.insert(result.end(), {"year", nullptr});
+ − 119 if (month.get())
+ − 120 result.insert(result.end(), {"month", *month});
+ − 121 else
+ − 122 result.insert(result.end(), {"month", nullptr});
+ − 123 if (day.get())
+ − 124 result.insert(result.end(), {"day", *day});
+ − 125 else
+ − 126 result.insert(result.end(), {"day", nullptr});
+ − 127 return result;
+ − 128 }