| 104 | } |
| 105 | |
| 106 | time_t StringToTimestamp(std::string const & s) |
| 107 | { |
| 108 | auto const size = s.size(); |
| 109 | if (size < 19) |
| 110 | return INVALID_TIME_STAMP; |
| 111 | |
| 112 | // Parse UTC format prefix: 1970-01-01T00:00:00 |
| 113 | tm t{}; |
| 114 | std::istringstream ss(s); |
| 115 | ss >> std::get_time(&t, "%Y-%m-%dT%H:%M:%S"); |
| 116 | |
| 117 | if (ss.fail()) |
| 118 | return INVALID_TIME_STAMP; |
| 119 | |
| 120 | time_t res = TimeGM(t); |
| 121 | |
| 122 | if (size == 19) |
| 123 | return res; // 1970-01-01T00:00:00 |
| 124 | |
| 125 | char signOrDotOrZ; |
| 126 | ss >> signOrDotOrZ; |
| 127 | |
| 128 | if (signOrDotOrZ == 'Z') |
| 129 | return res; // 1970-01-01T00:00:00Z |
| 130 | |
| 131 | // Fractional second values are dropped, as POSIX time_t doesn't hold them. |
| 132 | if (signOrDotOrZ == '.') |
| 133 | { |
| 134 | while (ss >> signOrDotOrZ && std::isdigit(signOrDotOrZ)) |
| 135 | {} |
| 136 | |
| 137 | if (ss.fail()) |
| 138 | return INVALID_TIME_STAMP; |
| 139 | |
| 140 | if (signOrDotOrZ == 'Z') |
| 141 | return res; // 1970-01-01T00:00:00.123Z |
| 142 | } |
| 143 | |
| 144 | if (signOrDotOrZ != '-' && signOrDotOrZ != '+') |
| 145 | return INVALID_TIME_STAMP; |
| 146 | |
| 147 | // Parse custom time zone offset format: 2012-12-03T00:38:34+03:30 |
| 148 | ss >> std::get_time(&t, "%H:%M"); |
| 149 | |
| 150 | if (ss.fail()) |
| 151 | return INVALID_TIME_STAMP; |
| 152 | |
| 153 | // Fix timezone offset |
| 154 | if (signOrDotOrZ == '-') |
| 155 | res = res + t.tm_hour * 3600 + t.tm_min * 60; |
| 156 | else // Positive offset should be subtracted. |
| 157 | res = res - t.tm_hour * 3600 - t.tm_min * 60; |
| 158 | |
| 159 | return res; |
| 160 | } |
| 161 | |
| 162 | time_t SecondsSinceEpochToTimeT(uint64_t secondsSinceEpoch) |
| 163 | { |