Scid  4.7.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
date.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////
2 //
3 // FILE: date.h
4 // Date format and inline date functions.
5 //
6 // Part of: Scid (Shane's Chess Information Database)
7 // Version: 1.9
8 //
9 // Notice: Copyright (c) 1999 Shane Hudson. All rights reserved.
10 //
11 // Author: Shane Hudson (sgh@users.sourceforge.net)
12 //
13 //////////////////////////////////////////////////////////////////////
14 
15 
16 #ifndef SCID_DATE_H
17 #define SCID_DATE_H
18 
19 #include "common.h"
20 #include <algorithm>
21 #include <cstdlib>
22 
23 // DATE STORAGE FORMAT:
24 // In memory, dates are stored in a 32-bit (4-byte) uint, of which only
25 // the lowest 3 bytes need be used, with the lowest 5 bits for the
26 // day, the next highest 4 bits for the month and the highest bits for
27 // the year. This makes date comparisons easy: a bigger date value is
28 // a more recent date. If a field is unknown, its value is set to zero.
29 // On disk, the date is stored in 3 bytes.
30 
31 
32 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
33 // CONSTANTS and MACROS:
34 
35 const dateT ZERO_DATE = 0;
36 
37 const uint YEAR_SHIFT = 9;
38 const uint MONTH_SHIFT = 5;
39 const uint DAY_SHIFT = 0;
40 
41 // DAY (31 days) 5 bits (32) , MONTH (12 months) 4 bits (16)
42 
43 const uint YEAR_MAX = 2047; // 2^11 - 1
44 
45 #define DATE_MAKE(y,m,d) (((y) << YEAR_SHIFT) | ((m) << MONTH_SHIFT) | (d))
46 
47 
48 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49 // date_GetYear():
50 // Get the year from a date.
51 inline uint
53 {
54  return (uint) (date >> YEAR_SHIFT);
55 }
56 
57 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
58 // date_GetMonth():
59 // Get the month from a date.
60 inline uint
62 {
63  return (uint) ((date >> MONTH_SHIFT) & 15);
64 }
65 
66 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67 //### date_GetDay():
68 // Get the day of the month from a date.
69 inline uint
71 {
72  return (uint) (date & 31);
73 }
74 
75 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
76 //### date_GetMonthDay():
77 // Get the month and day; used to check for year-only dates. S.A
78 inline uint
80 {
81  return (uint) (date & 511);
82 }
83 
84 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
85 // date_DecodeToString(): convert date to PGN tag string.
86 inline void
88 {
89  ASSERT(str != NULL);
90  uint year, month, day;
91 
92  year = date_GetYear (date);
93  month = date_GetMonth (date);
94  day = date_GetDay (date);
95 
96  if (year == 0) {
97  *str++ = '?'; *str++ = '?'; *str++ = '?'; *str++ = '?';
98  } else {
99  *str++ = '0' + (year / 1000);
100  *str++ = '0' + (year % 1000) / 100;
101  *str++ = '0' + (year % 100) / 10;
102  *str++ = '0' + (year % 10);
103  }
104  *str++ = '.';
105 
106  if (month == 0) {
107  *str++ = '?'; *str++ = '?';
108  } else {
109  *str++ = '0' + (month / 10);
110  *str++ = '0' + (month % 10);
111  }
112  *str++ = '.';
113 
114  if (day == 0) {
115  *str++ = '?'; *str++ = '?';
116  } else {
117  *str++ = '0' + (day / 10);
118  *str++ = '0' + (day % 10);
119  }
120  *str = 0;
121 }
122 
123 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
124 // date_EncodeFromString(): convert PGN tag string to date.
125 // The date string format is: "yyyy.mm.dd".
126 inline dateT
127 date_EncodeFromString (const char * str)
128 {
129  // Do checks on str's validity as a date string:
130  ASSERT(str != NULL);
131 
132  dateT date;
133  uint year, month, day;
134 
135  // convert year:
136  year = std::strtoul(str, NULL, 10);
137  if (year > YEAR_MAX) { year = 0; }
138  date = year << YEAR_SHIFT;
139  while (*str != 0 && *str != '.') { str++; }
140  if (*str == '.') { str++; }
141 
142  // convert month:
143  month = std::strtoul(str, NULL, 10);
144  if (month > 12) { return date; }
145  date |= (month << MONTH_SHIFT);
146  while (*str != 0 && *str != '.') { str++; }
147  if (*str == '.') { str++; }
148 
149  // convert day:
150  day = std::strtoul(str, NULL, 10);
151  if (day > 31) { return date; }
152  date |= (day << DAY_SHIFT);
153 
154  return date;
155 }
156 
157 /**
158  * Creates a dateT object from a PGN tag value string.
159  * "The Date tag value field always uses a standard ten character format:
160  * "YYYY.MM.DD". If the any of the digit fields are not known, then question
161  * marks are used in place of the digits."
162  * @param str: pointer to the memory containing the tag value.
163  * @param len: length of the tag value.
164  * @returns the dateT object corresponding to @e str.
165  */
166 inline dateT date_parsePGNTag(const char* str, size_t len) {
167  char tmp[10] = {0};
168  std::transform(str, str + std::min<size_t>(len, 10), tmp, [](char ch) {
169  return (ch >= '0' && ch <= '9') ? ch - '0' : 0;
170  });
171 
172  uint32_t year = tmp[0] * 1000 + tmp[1] * 100 + tmp[2] * 10 + tmp[3];
173  uint32_t month = tmp[5] * 10 + tmp[6];
174  uint32_t day = tmp[8] * 10 + tmp[9];
175 
176  if (year > YEAR_MAX)
177  year = 0;
178 
179  if (month > 12)
180  month = 0;
181 
182  constexpr unsigned char days[] = {31, 31, 28, 31, 30, 31, 30,
183  31, 31, 30, 31, 30, 31};
184  if (day > days[month]) {
185  if (day != 29 || year % 4 || (year % 100 == 0 && year % 400)) {
186  day = 0;
187  }
188  }
189 
190  return (year << YEAR_SHIFT) | (month << MONTH_SHIFT) | (day << DAY_SHIFT);
191 }
192 
193 inline dateT date_parsePGNTag(std::pair<const char*, const char*> str) {
194  return date_parsePGNTag(str.first, std::distance(str.first, str.second));
195 }
196 
197 #endif // #ifndef SCID_DATE_H
198 
199 //////////////////////////////////////////////////////////////////////
200 // EOF: date.h
201 //////////////////////////////////////////////////////////////////////
202 
uint date_GetYear(dateT date)
Definition: date.h:52
const uint YEAR_MAX
Definition: date.h:43
const uint MONTH_SHIFT
Definition: date.h:38
const uint YEAR_SHIFT
Definition: date.h:37
uint dateT
Definition: common.h:147
#define ASSERT(f)
Definition: common.h:59
dateT date_parsePGNTag(const char *str, size_t len)
Creates a dateT object from a PGN tag value string.
Definition: date.h:166
void date_DecodeToString(dateT date, char *str)
Definition: date.h:87
const dateT ZERO_DATE
Definition: date.h:35
uint32_t uint
Definition: common.h:91
const uint DAY_SHIFT
Definition: date.h:39
uint date_GetMonthDay(dateT date)
Definition: date.h:79
uint date_GetMonth(dateT date)
Definition: date.h:61
dateT date_EncodeFromString(const char *str)
Definition: date.h:127
uint date_GetDay(dateT date)
Definition: date.h:70