summaryrefslogtreecommitdiff
path: root/src/google/protobuf/stubs/time.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/stubs/time.cc')
-rw-r--r--src/google/protobuf/stubs/time.cc365
1 files changed, 0 insertions, 365 deletions
diff --git a/src/google/protobuf/stubs/time.cc b/src/google/protobuf/stubs/time.cc
deleted file mode 100644
index 49c0412c..00000000
--- a/src/google/protobuf/stubs/time.cc
+++ /dev/null
@@ -1,365 +0,0 @@
-#include <google/protobuf/stubs/time.h>
-
-#include <ctime>
-
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-
-namespace {
-static const int64 kSecondsPerMinute = 60;
-static const int64 kSecondsPerHour = 3600;
-static const int64 kSecondsPerDay = kSecondsPerHour * 24;
-static const int64 kSecondsPer400Years =
- kSecondsPerDay * (400 * 365 + 400 / 4 - 3);
-// Seconds from 0001-01-01T00:00:00 to 1970-01-01T:00:00:00
-static const int64 kSecondsFromEraToEpoch = 62135596800LL;
-// The range of timestamp values we support.
-static const int64 kMinTime = -62135596800LL; // 0001-01-01T00:00:00
-static const int64 kMaxTime = 253402300799LL; // 9999-12-31T23:59:59
-
-static const int kNanosPerMillisecond = 1000000;
-static const int kNanosPerMicrosecond = 1000;
-
-// Count the seconds from the given year (start at Jan 1, 00:00) to 100 years
-// after.
-int64 SecondsPer100Years(int year) {
- if (year % 400 == 0 || year % 400 > 300) {
- return kSecondsPerDay * (100 * 365 + 100 / 4);
- } else {
- return kSecondsPerDay * (100 * 365 + 100 / 4 - 1);
- }
-}
-
-// Count the seconds from the given year (start at Jan 1, 00:00) to 4 years
-// after.
-int64 SecondsPer4Years(int year) {
- if ((year % 100 == 0 || year % 100 > 96) &&
- !(year % 400 == 0 || year % 400 > 396)) {
- // No leap years.
- return kSecondsPerDay * (4 * 365);
- } else {
- // One leap years.
- return kSecondsPerDay * (4 * 365 + 1);
- }
-}
-
-bool IsLeapYear(int year) {
- return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
-}
-
-int64 SecondsPerYear(int year) {
- return kSecondsPerDay * (IsLeapYear(year) ? 366 : 365);
-}
-
-static const int kDaysInMonth[13] = {
- 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-int64 SecondsPerMonth(int month, bool leap) {
- if (month == 2 && leap) {
- return kSecondsPerDay * (kDaysInMonth[month] + 1);
- }
- return kSecondsPerDay * kDaysInMonth[month];
-}
-
-static const int kDaysSinceJan[13] = {
- 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
-};
-
-bool ValidateDateTime(const DateTime& time) {
- if (time.year < 1 || time.year > 9999 ||
- time.month < 1 || time.month > 12 ||
- time.day < 1 || time.day > 31 ||
- time.hour < 0 || time.hour > 23 ||
- time.minute < 0 || time.minute > 59 ||
- time.second < 0 || time.second > 59) {
- return false;
- }
- if (time.month == 2 && IsLeapYear(time.year)) {
- return time.month <= kDaysInMonth[time.month] + 1;
- } else {
- return time.month <= kDaysInMonth[time.month];
- }
-}
-
-// Count the number of seconds elapsed from 0001-01-01T00:00:00 to the given
-// time.
-int64 SecondsSinceCommonEra(const DateTime& time) {
- int64 result = 0;
- // Years should be between 1 and 9999.
- assert(time.year >= 1 && time.year <= 9999);
- int year = 1;
- if ((time.year - year) >= 400) {
- int count_400years = (time.year - year) / 400;
- result += kSecondsPer400Years * count_400years;
- year += count_400years * 400;
- }
- while ((time.year - year) >= 100) {
- result += SecondsPer100Years(year);
- year += 100;
- }
- while ((time.year - year) >= 4) {
- result += SecondsPer4Years(year);
- year += 4;
- }
- while (time.year > year) {
- result += SecondsPerYear(year);
- ++year;
- }
- // Months should be between 1 and 12.
- assert(time.month >= 1 && time.month <= 12);
- int month = time.month;
- result += kSecondsPerDay * kDaysSinceJan[month];
- if (month > 2 && IsLeapYear(year)) {
- result += kSecondsPerDay;
- }
- assert(time.day >= 1 &&
- time.day <= (month == 2 && IsLeapYear(year)
- ? kDaysInMonth[month] + 1
- : kDaysInMonth[month]));
- result += kSecondsPerDay * (time.day - 1);
- result += kSecondsPerHour * time.hour +
- kSecondsPerMinute * time.minute +
- time.second;
- return result;
-}
-
-// Format nanoseconds with either 3, 6, or 9 digits depending on the required
-// precision to represent the exact value.
-string FormatNanos(int32 nanos) {
- if (nanos % kNanosPerMillisecond == 0) {
- return StringPrintf("%03d", nanos / kNanosPerMillisecond);
- } else if (nanos % kNanosPerMicrosecond == 0) {
- return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
- } else {
- return StringPrintf("%09d", nanos);
- }
-}
-
-// Parses an integer from a null-terminated char sequence. The method
-// consumes at most "width" chars. Returns a pointer after the consumed
-// integer, or NULL if the data does not start with an integer or the
-// integer value does not fall in the range of [min_value, max_value].
-const char* ParseInt(const char* data, int width, int min_value,
- int max_value, int* result) {
- if (!ascii_isdigit(*data)) {
- return NULL;
- }
- int value = 0;
- for (int i = 0; i < width; ++i, ++data) {
- if (ascii_isdigit(*data)) {
- value = value * 10 + (*data - '0');
- } else {
- break;
- }
- }
- if (value >= min_value && value <= max_value) {
- *result = value;
- return data;
- } else {
- return NULL;
- }
-}
-
-// Consumes the fractional parts of a second into nanos. For example,
-// "010" will be parsed to 10000000 nanos.
-const char* ParseNanos(const char* data, int32* nanos) {
- if (!ascii_isdigit(*data)) {
- return NULL;
- }
- int value = 0;
- int len = 0;
- // Consume as many digits as there are but only take the first 9 into
- // account.
- while (ascii_isdigit(*data)) {
- if (len < 9) {
- value = value * 10 + *data - '0';
- }
- ++len;
- ++data;
- }
- while (len < 9) {
- value = value * 10;
- ++len;
- }
- *nanos = value;
- return data;
-}
-
-const char* ParseTimezoneOffset(const char* data, int64* offset) {
- // Accept format "HH:MM". E.g., "08:00"
- int hour;
- if ((data = ParseInt(data, 2, 0, 23, &hour)) == NULL) {
- return NULL;
- }
- if (*data++ != ':') {
- return NULL;
- }
- int minute;
- if ((data = ParseInt(data, 2, 0, 59, &minute)) == NULL) {
- return NULL;
- }
- *offset = (hour * 60 + minute) * 60;
- return data;
-}
-} // namespace
-
-bool SecondsToDateTime(int64 seconds, DateTime* time) {
- if (seconds < kMinTime || seconds > kMaxTime) {
- return false;
- }
- // It's easier to calcuate the DateTime starting from 0001-01-01T00:00:00
- seconds = seconds + kSecondsFromEraToEpoch;
- int year = 1;
- if (seconds >= kSecondsPer400Years) {
- int count_400years = seconds / kSecondsPer400Years;
- year += 400 * count_400years;
- seconds %= kSecondsPer400Years;
- }
- while (seconds >= SecondsPer100Years(year)) {
- seconds -= SecondsPer100Years(year);
- year += 100;
- }
- while (seconds >= SecondsPer4Years(year)) {
- seconds -= SecondsPer4Years(year);
- year += 4;
- }
- while (seconds >= SecondsPerYear(year)) {
- seconds -= SecondsPerYear(year);
- year += 1;
- }
- bool leap = IsLeapYear(year);
- int month = 1;
- while (seconds >= SecondsPerMonth(month, leap)) {
- seconds -= SecondsPerMonth(month, leap);
- ++month;
- }
- int day = 1 + seconds / kSecondsPerDay;
- seconds %= kSecondsPerDay;
- int hour = seconds / kSecondsPerHour;
- seconds %= kSecondsPerHour;
- int minute = seconds / kSecondsPerMinute;
- seconds %= kSecondsPerMinute;
- time->year = year;
- time->month = month;
- time->day = day;
- time->hour = hour;
- time->minute = minute;
- time->second = static_cast<int>(seconds);
- return true;
-}
-
-bool DateTimeToSeconds(const DateTime& time, int64* seconds) {
- if (!ValidateDateTime(time)) {
- return false;
- }
- *seconds = SecondsSinceCommonEra(time) - kSecondsFromEraToEpoch;
- return true;
-}
-
-void GetCurrentTime(int64* seconds, int32* nanos) {
- // TODO(xiaofeng): Improve the accuracy of this implementation (or just
- // remove this method from protobuf).
- *seconds = time(NULL);
- *nanos = 0;
-}
-
-string FormatTime(int64 seconds, int32 nanos) {
- DateTime time;
- if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) {
- return "InvalidTime";
- }
- string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
- time.year, time.month, time.day,
- time.hour, time.minute, time.second);
- if (nanos != 0) {
- result += "." + FormatNanos(nanos);
- }
- return result + "Z";
-}
-
-bool ParseTime(const string& value, int64* seconds, int32* nanos) {
- DateTime time;
- const char* data = value.c_str();
- // We only accept:
- // Z-normalized: 2015-05-20T13:29:35.120Z
- // With UTC offset: 2015-05-20T13:29:35.120-08:00
-
- // Parse year
- if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == NULL) {
- return false;
- }
- // Expect '-'
- if (*data++ != '-') return false;
- // Parse month
- if ((data = ParseInt(data, 2, 1, 12, &time.month)) == NULL) {
- return false;
- }
- // Expect '-'
- if (*data++ != '-') return false;
- // Parse day
- if ((data = ParseInt(data, 2, 1, 31, &time.day)) == NULL) {
- return false;
- }
- // Expect 'T'
- if (*data++ != 'T') return false;
- // Parse hour
- if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == NULL) {
- return false;
- }
- // Expect ':'
- if (*data++ != ':') return false;
- // Parse minute
- if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == NULL) {
- return false;
- }
- // Expect ':'
- if (*data++ != ':') return false;
- // Parse second
- if ((data = ParseInt(data, 2, 0, 59, &time.second)) == NULL) {
- return false;
- }
- if (!DateTimeToSeconds(time, seconds)) {
- return false;
- }
- // Parse nanoseconds.
- if (*data == '.') {
- ++data;
- // Parse nanoseconds.
- if ((data = ParseNanos(data, nanos)) == NULL) {
- return false;
- }
- } else {
- *nanos = 0;
- }
- // Parse UTC offsets.
- if (*data == 'Z') {
- ++data;
- } else if (*data == '+') {
- ++data;
- int64 offset;
- if ((data = ParseTimezoneOffset(data, &offset)) == NULL) {
- return false;
- }
- *seconds -= offset;
- } else if (*data == '-') {
- ++data;
- int64 offset;
- if ((data = ParseTimezoneOffset(data, &offset)) == NULL) {
- return false;
- }
- *seconds += offset;
- } else {
- return false;
- }
- // Done with parsing.
- return *data == 0;
-}
-
-} // namespace internal
-} // namespace protobuf
-} // namespace google