~singpolyma/biboumi

ref: 19ed2e7f5f182570c894a0a89d154f973fb01906 biboumi/src/utils/time.cpp -rw-r--r-- 1.8 KiB
19ed2e7f — louiz’ Fix the datetime parsing to handle optional fractions of seconds 5 years ago
                                                                                
7536a1b3 louiz’
1a09c965 louiz’
7536a1b3 louiz’
548e4ad4 louiz’
0ab40dc1 louiz’
c54f28d2 louiz’
7536a1b3 louiz’
2a4905df louiz’
7536a1b3 louiz’
1140db3b louiz’
548e4ad4 louiz’
c54f28d2 louiz’
548e4ad4 louiz’
835c650e louiz’
548e4ad4 louiz’
19ed2e7f louiz’
548e4ad4 louiz’
c54f28d2 louiz’
19ed2e7f louiz’
c54f28d2 louiz’
548e4ad4 louiz’
19ed2e7f louiz’
1140db3b louiz’
548e4ad4 louiz’
19ed2e7f louiz’
548e4ad4 louiz’
1140db3b louiz’
aaa2ca67 louiz’
548e4ad4 louiz’
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <utils/time.hpp>
#include <ctime>

#include <sstream>
#include <iomanip>
#include <locale>

#include "biboumi.h"

namespace utils
{
std::string to_string(const std::time_t& timestamp)
{
  constexpr std::size_t stamp_size = 21;
  char date_buf[stamp_size];
  if (std::strftime(date_buf, stamp_size, "%FT%TZ", std::gmtime(&timestamp)) != stamp_size - 1)
    return "";
  return {std::begin(date_buf), std::end(date_buf) - 1};
}

std::time_t parse_datetime(const std::string& stamp)
{
  static const char* format = "%Y-%m-%dT%H:%M:%S";
  std::tm t = {};
#ifdef HAS_GET_TIME
  std::istringstream ss(stamp);
  ss.imbue(std::locale("C"));

  std::string remainings;
  ss >> std::get_time(&t, format) >> remainings;
  if (ss.fail())
    return -1;
#else
                                             /* Y   -   m   -   d   T   H   :   M   :   S */
  constexpr std::size_t stamp_size_without_tz = 4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2;
  if (!strptime(stamp.data(), format, &t)) {
    return -1;
  }
  const std::string remainings(stamp.data() + stamp_size_without_tz);
#endif

  if (remainings.empty())
    return -1;

  std::string timezone;
  // Skip optional fractions of seconds
  if (remainings[0] == '.')
    {
      const auto pos = remainings.find_first_not_of(".0123456789");
      timezone = remainings.substr(pos);
    }
  else
    timezone = std::move(remainings);

  if (timezone.compare(0, 1, "Z") != 0)
    {
      std::stringstream tz_ss;
      tz_ss << timezone;
      int multiplier = -1;
      char prefix;
      int hours;
      char sep;
      int minutes;
      tz_ss >> prefix >> hours >> sep >> minutes;
      if (tz_ss.fail())
        return -1;
      if (prefix == '-')
        multiplier = +1;
      else if (prefix != '+')
        return -1;

      t.tm_hour += multiplier * hours;
      t.tm_min += multiplier * minutes;
    }
  return ::timegm(&t);
}

}