诸暨麻将添加redis
您不能選擇超過 %s 個話題 話題必須以字母或數字為開頭,可包含連接號 ('-') 且最長為 35 個字
 
 
 
 
 
 

366 行
10 KiB

  1. #include <google/protobuf/stubs/time.h>
  2. #include <ctime>
  3. #include <google/protobuf/stubs/stringprintf.h>
  4. #include <google/protobuf/stubs/strutil.h>
  5. namespace google {
  6. namespace protobuf {
  7. namespace internal {
  8. namespace {
  9. static const int64 kSecondsPerMinute = 60;
  10. static const int64 kSecondsPerHour = 3600;
  11. static const int64 kSecondsPerDay = kSecondsPerHour * 24;
  12. static const int64 kSecondsPer400Years =
  13. kSecondsPerDay * (400 * 365 + 400 / 4 - 3);
  14. // Seconds from 0001-01-01T00:00:00 to 1970-01-01T:00:00:00
  15. static const int64 kSecondsFromEraToEpoch = 62135596800LL;
  16. // The range of timestamp values we support.
  17. static const int64 kMinTime = -62135596800LL; // 0001-01-01T00:00:00
  18. static const int64 kMaxTime = 253402300799LL; // 9999-12-31T23:59:59
  19. static const int kNanosPerMillisecond = 1000000;
  20. static const int kNanosPerMicrosecond = 1000;
  21. // Count the seconds from the given year (start at Jan 1, 00:00) to 100 years
  22. // after.
  23. int64 SecondsPer100Years(int year) {
  24. if (year % 400 == 0 || year % 400 > 300) {
  25. return kSecondsPerDay * (100 * 365 + 100 / 4);
  26. } else {
  27. return kSecondsPerDay * (100 * 365 + 100 / 4 - 1);
  28. }
  29. }
  30. // Count the seconds from the given year (start at Jan 1, 00:00) to 4 years
  31. // after.
  32. int64 SecondsPer4Years(int year) {
  33. if ((year % 100 == 0 || year % 100 > 96) &&
  34. !(year % 400 == 0 || year % 400 > 396)) {
  35. // No leap years.
  36. return kSecondsPerDay * (4 * 365);
  37. } else {
  38. // One leap years.
  39. return kSecondsPerDay * (4 * 365 + 1);
  40. }
  41. }
  42. bool IsLeapYear(int year) {
  43. return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
  44. }
  45. int64 SecondsPerYear(int year) {
  46. return kSecondsPerDay * (IsLeapYear(year) ? 366 : 365);
  47. }
  48. static const int kDaysInMonth[13] = {
  49. 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  50. };
  51. int64 SecondsPerMonth(int month, bool leap) {
  52. if (month == 2 && leap) {
  53. return kSecondsPerDay * (kDaysInMonth[month] + 1);
  54. }
  55. return kSecondsPerDay * kDaysInMonth[month];
  56. }
  57. static const int kDaysSinceJan[13] = {
  58. 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
  59. };
  60. bool ValidateDateTime(const DateTime& time) {
  61. if (time.year < 1 || time.year > 9999 ||
  62. time.month < 1 || time.month > 12 ||
  63. time.day < 1 || time.day > 31 ||
  64. time.hour < 0 || time.hour > 23 ||
  65. time.minute < 0 || time.minute > 59 ||
  66. time.second < 0 || time.second > 59) {
  67. return false;
  68. }
  69. if (time.month == 2 && IsLeapYear(time.year)) {
  70. return time.day <= kDaysInMonth[time.month] + 1;
  71. } else {
  72. return time.day <= kDaysInMonth[time.month];
  73. }
  74. }
  75. // Count the number of seconds elapsed from 0001-01-01T00:00:00 to the given
  76. // time.
  77. int64 SecondsSinceCommonEra(const DateTime& time) {
  78. int64 result = 0;
  79. // Years should be between 1 and 9999.
  80. assert(time.year >= 1 && time.year <= 9999);
  81. int year = 1;
  82. if ((time.year - year) >= 400) {
  83. int count_400years = (time.year - year) / 400;
  84. result += kSecondsPer400Years * count_400years;
  85. year += count_400years * 400;
  86. }
  87. while ((time.year - year) >= 100) {
  88. result += SecondsPer100Years(year);
  89. year += 100;
  90. }
  91. while ((time.year - year) >= 4) {
  92. result += SecondsPer4Years(year);
  93. year += 4;
  94. }
  95. while (time.year > year) {
  96. result += SecondsPerYear(year);
  97. ++year;
  98. }
  99. // Months should be between 1 and 12.
  100. assert(time.month >= 1 && time.month <= 12);
  101. int month = time.month;
  102. result += kSecondsPerDay * kDaysSinceJan[month];
  103. if (month > 2 && IsLeapYear(year)) {
  104. result += kSecondsPerDay;
  105. }
  106. assert(time.day >= 1 &&
  107. time.day <= (month == 2 && IsLeapYear(year)
  108. ? kDaysInMonth[month] + 1
  109. : kDaysInMonth[month]));
  110. result += kSecondsPerDay * (time.day - 1);
  111. result += kSecondsPerHour * time.hour +
  112. kSecondsPerMinute * time.minute +
  113. time.second;
  114. return result;
  115. }
  116. // Format nanoseconds with either 3, 6, or 9 digits depending on the required
  117. // precision to represent the exact value.
  118. string FormatNanos(int32 nanos) {
  119. if (nanos % kNanosPerMillisecond == 0) {
  120. return StringPrintf("%03d", nanos / kNanosPerMillisecond);
  121. } else if (nanos % kNanosPerMicrosecond == 0) {
  122. return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
  123. } else {
  124. return StringPrintf("%09d", nanos);
  125. }
  126. }
  127. // Parses an integer from a null-terminated char sequence. The method
  128. // consumes at most "width" chars. Returns a pointer after the consumed
  129. // integer, or nullptr if the data does not start with an integer or the
  130. // integer value does not fall in the range of [min_value, max_value].
  131. const char* ParseInt(const char* data, int width, int min_value,
  132. int max_value, int* result) {
  133. if (!ascii_isdigit(*data)) {
  134. return nullptr;
  135. }
  136. int value = 0;
  137. for (int i = 0; i < width; ++i, ++data) {
  138. if (ascii_isdigit(*data)) {
  139. value = value * 10 + (*data - '0');
  140. } else {
  141. break;
  142. }
  143. }
  144. if (value >= min_value && value <= max_value) {
  145. *result = value;
  146. return data;
  147. } else {
  148. return nullptr;
  149. }
  150. }
  151. // Consumes the fractional parts of a second into nanos. For example,
  152. // "010" will be parsed to 10000000 nanos.
  153. const char* ParseNanos(const char* data, int32* nanos) {
  154. if (!ascii_isdigit(*data)) {
  155. return nullptr;
  156. }
  157. int value = 0;
  158. int len = 0;
  159. // Consume as many digits as there are but only take the first 9 into
  160. // account.
  161. while (ascii_isdigit(*data)) {
  162. if (len < 9) {
  163. value = value * 10 + *data - '0';
  164. }
  165. ++len;
  166. ++data;
  167. }
  168. while (len < 9) {
  169. value = value * 10;
  170. ++len;
  171. }
  172. *nanos = value;
  173. return data;
  174. }
  175. const char* ParseTimezoneOffset(const char* data, int64* offset) {
  176. // Accept format "HH:MM". E.g., "08:00"
  177. int hour;
  178. if ((data = ParseInt(data, 2, 0, 23, &hour)) == nullptr) {
  179. return nullptr;
  180. }
  181. if (*data++ != ':') {
  182. return nullptr;
  183. }
  184. int minute;
  185. if ((data = ParseInt(data, 2, 0, 59, &minute)) == nullptr) {
  186. return nullptr;
  187. }
  188. *offset = (hour * 60 + minute) * 60;
  189. return data;
  190. }
  191. } // namespace
  192. bool SecondsToDateTime(int64 seconds, DateTime* time) {
  193. if (seconds < kMinTime || seconds > kMaxTime) {
  194. return false;
  195. }
  196. // It's easier to calcuate the DateTime starting from 0001-01-01T00:00:00
  197. seconds = seconds + kSecondsFromEraToEpoch;
  198. int year = 1;
  199. if (seconds >= kSecondsPer400Years) {
  200. int count_400years = seconds / kSecondsPer400Years;
  201. year += 400 * count_400years;
  202. seconds %= kSecondsPer400Years;
  203. }
  204. while (seconds >= SecondsPer100Years(year)) {
  205. seconds -= SecondsPer100Years(year);
  206. year += 100;
  207. }
  208. while (seconds >= SecondsPer4Years(year)) {
  209. seconds -= SecondsPer4Years(year);
  210. year += 4;
  211. }
  212. while (seconds >= SecondsPerYear(year)) {
  213. seconds -= SecondsPerYear(year);
  214. year += 1;
  215. }
  216. bool leap = IsLeapYear(year);
  217. int month = 1;
  218. while (seconds >= SecondsPerMonth(month, leap)) {
  219. seconds -= SecondsPerMonth(month, leap);
  220. ++month;
  221. }
  222. int day = 1 + seconds / kSecondsPerDay;
  223. seconds %= kSecondsPerDay;
  224. int hour = seconds / kSecondsPerHour;
  225. seconds %= kSecondsPerHour;
  226. int minute = seconds / kSecondsPerMinute;
  227. seconds %= kSecondsPerMinute;
  228. time->year = year;
  229. time->month = month;
  230. time->day = day;
  231. time->hour = hour;
  232. time->minute = minute;
  233. time->second = static_cast<int>(seconds);
  234. return true;
  235. }
  236. bool DateTimeToSeconds(const DateTime& time, int64* seconds) {
  237. if (!ValidateDateTime(time)) {
  238. return false;
  239. }
  240. *seconds = SecondsSinceCommonEra(time) - kSecondsFromEraToEpoch;
  241. return true;
  242. }
  243. void GetCurrentTime(int64* seconds, int32* nanos) {
  244. // TODO(xiaofeng): Improve the accuracy of this implementation (or just
  245. // remove this method from protobuf).
  246. *seconds = time(nullptr);
  247. *nanos = 0;
  248. }
  249. string FormatTime(int64 seconds, int32 nanos) {
  250. DateTime time;
  251. if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) {
  252. return "InvalidTime";
  253. }
  254. string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
  255. time.year, time.month, time.day,
  256. time.hour, time.minute, time.second);
  257. if (nanos != 0) {
  258. result += "." + FormatNanos(nanos);
  259. }
  260. return result + "Z";
  261. }
  262. bool ParseTime(const string& value, int64* seconds, int32* nanos) {
  263. DateTime time;
  264. const char* data = value.c_str();
  265. // We only accept:
  266. // Z-normalized: 2015-05-20T13:29:35.120Z
  267. // With UTC offset: 2015-05-20T13:29:35.120-08:00
  268. // Parse year
  269. if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == nullptr) {
  270. return false;
  271. }
  272. // Expect '-'
  273. if (*data++ != '-') return false;
  274. // Parse month
  275. if ((data = ParseInt(data, 2, 1, 12, &time.month)) == nullptr) {
  276. return false;
  277. }
  278. // Expect '-'
  279. if (*data++ != '-') return false;
  280. // Parse day
  281. if ((data = ParseInt(data, 2, 1, 31, &time.day)) == nullptr) {
  282. return false;
  283. }
  284. // Expect 'T'
  285. if (*data++ != 'T') return false;
  286. // Parse hour
  287. if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == nullptr) {
  288. return false;
  289. }
  290. // Expect ':'
  291. if (*data++ != ':') return false;
  292. // Parse minute
  293. if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == nullptr) {
  294. return false;
  295. }
  296. // Expect ':'
  297. if (*data++ != ':') return false;
  298. // Parse second
  299. if ((data = ParseInt(data, 2, 0, 59, &time.second)) == nullptr) {
  300. return false;
  301. }
  302. if (!DateTimeToSeconds(time, seconds)) {
  303. return false;
  304. }
  305. // Parse nanoseconds.
  306. if (*data == '.') {
  307. ++data;
  308. // Parse nanoseconds.
  309. if ((data = ParseNanos(data, nanos)) == nullptr) {
  310. return false;
  311. }
  312. } else {
  313. *nanos = 0;
  314. }
  315. // Parse UTC offsets.
  316. if (*data == 'Z') {
  317. ++data;
  318. } else if (*data == '+') {
  319. ++data;
  320. int64 offset;
  321. if ((data = ParseTimezoneOffset(data, &offset)) == nullptr) {
  322. return false;
  323. }
  324. *seconds -= offset;
  325. } else if (*data == '-') {
  326. ++data;
  327. int64 offset;
  328. if ((data = ParseTimezoneOffset(data, &offset)) == nullptr) {
  329. return false;
  330. }
  331. *seconds += offset;
  332. } else {
  333. return false;
  334. }
  335. // Done with parsing.
  336. return *data == 0;
  337. }
  338. } // namespace internal
  339. } // namespace protobuf
  340. } // namespace google