39typedef uint32_t dateT;
41const dateT ZERO_DATE = 0;
43const uint32_t YEAR_SHIFT = 9;
44const uint32_t MONTH_SHIFT = 5;
45const uint32_t DAY_SHIFT = 0;
49const uint32_t YEAR_MAX = 2047;
51#define DATE_MAKE(y,m,d) (((y) << scid::core::YEAR_SHIFT) | ((m) << scid::core::MONTH_SHIFT) | (d))
58date_GetYear (dateT date)
60 return (uint32_t) (date >> YEAR_SHIFT);
67date_GetMonth (dateT date)
69 return (uint32_t) ((date >> MONTH_SHIFT) & 15);
76date_GetDay (dateT date)
78 return (uint32_t) (date & 31);
82inline bool date_isPartial(dateT date) {
83 return date_GetYear(date) == 0 || date_GetMonth(date) == 0 ||
84 date_GetDay(date) == 0;
90date_DecodeToString (dateT date,
char * str)
93 uint32_t year, month, day;
95 year = date_GetYear (date);
96 month = date_GetMonth (date);
97 day = date_GetDay (date);
100 *str++ =
'?'; *str++ =
'?'; *str++ =
'?'; *str++ =
'?';
102 *str++ =
'0' + (year / 1000);
103 *str++ =
'0' + (year % 1000) / 100;
104 *str++ =
'0' + (year % 100) / 10;
105 *str++ =
'0' + (year % 10);
110 *str++ =
'?'; *str++ =
'?';
112 *str++ =
'0' + (month / 10);
113 *str++ =
'0' + (month % 10);
118 *str++ =
'?'; *str++ =
'?';
120 *str++ =
'0' + (day / 10);
121 *str++ =
'0' + (day % 10);
130date_EncodeFromString (
const char * str)
136 uint32_t year, month, day;
139 year = std::strtoul(str, NULL, 10);
140 if (year > YEAR_MAX) { year = 0; }
141 date = year << YEAR_SHIFT;
142 while (*str != 0 && *str !=
'.') { str++; }
143 if (*str ==
'.') { str++; }
146 month = std::strtoul(str, NULL, 10);
147 if (month > 12) {
return date; }
148 date |= (month << MONTH_SHIFT);
149 while (*str != 0 && *str !=
'.') { str++; }
150 if (*str ==
'.') { str++; }
153 day = std::strtoul(str, NULL, 10);
154 if (day > 31) {
return date; }
155 date |= (day << DAY_SHIFT);
169inline dateT date_parsePGNTag(
const char* str,
size_t len) {
170 auto is_digit = [](
auto v) {
return v >= 0 && v <= 9; };
172 if (len < 4 || len > 10)
176 std::transform(str, str + len, tmp, [](
unsigned char ch) {
177 return ch -
static_cast<unsigned char>(
'0');
179 std::fill(tmp + len, tmp + 10, -1);
181 uint32_t year = tmp[0] * 1000 + tmp[1] * 100 + tmp[2] * 10 + tmp[3];
182 if (!std::all_of(tmp, tmp + 4, is_digit) || year > YEAR_MAX)
186 if (!is_digit(tmp[4]) && is_digit(tmp[5])) {
187 if (!is_digit(tmp[6])) {
189 std::rotate(tmp + 5, tmp + 9, tmp + 10);
192 month = tmp[5] * 10 + tmp[6];
198 if (!is_digit(tmp[7]) && is_digit(tmp[8])) {
199 day = is_digit(tmp[9]) ? tmp[8] * 10 + tmp[9] : tmp[8];
204 return (year << YEAR_SHIFT) | (month << MONTH_SHIFT) | (day << DAY_SHIFT);
207inline dateT date_parsePGNTag(std::pair<const char*, const char*> str) {
208 return date_parsePGNTag(str.first, std::distance(str.first, str.second));