summaryrefslogtreecommitdiffstats
path: root/src/base/date_time_scanner.cc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/base/date_time_scanner.cc117
1 files changed, 79 insertions, 38 deletions
diff --git a/src/base/date_time_scanner.cc b/src/base/date_time_scanner.cc
index 72b7e5d..c3a904b 100644
--- a/src/base/date_time_scanner.cc
+++ b/src/base/date_time_scanner.cc
@@ -34,6 +34,8 @@
#include "date_time_scanner.hh"
#include "config.h"
+#include "date_time_scanner.cfg.hh"
+#include "injector.hh"
#include "ptimec.hh"
#include "scn/scn.h"
@@ -45,17 +47,28 @@ date_time_scanner::ftime(char* dst,
{
off_t off = 0;
- if (time_fmt == nullptr) {
- PTIMEC_FORMATS[this->dts_fmt_lock].pf_ffunc(dst, off, len, tm);
- if (tm.et_flags & ETF_MILLIS_SET) {
- dst[off++] = '.';
- ftime_L(dst, off, len, tm);
- } else if (tm.et_flags & ETF_MICROS_SET) {
- dst[off++] = '.';
- ftime_f(dst, off, len, tm);
- } else if (tm.et_flags & ETF_NANOS_SET) {
- dst[off++] = '.';
- ftime_N(dst, off, len, tm);
+ if (time_fmt == nullptr || this->dts_fmt_lock == -1
+ || (tm.et_flags & ETF_MACHINE_ORIENTED))
+ {
+ auto index
+ = this->dts_fmt_lock != -1 && !(tm.et_flags & ETF_MACHINE_ORIENTED)
+ ? this->dts_fmt_lock
+ : PTIMEC_DEFAULT_FMT_INDEX;
+ PTIMEC_FORMATS[index].pf_ffunc(dst, off, len, tm);
+ if (tm.et_flags & ETF_SUB_NOT_IN_FORMAT) {
+ if (tm.et_flags & ETF_MILLIS_SET) {
+ dst[off++] = '.';
+ ftime_L(dst, off, len, tm);
+ } else if (tm.et_flags & ETF_MICROS_SET) {
+ dst[off++] = '.';
+ ftime_f(dst, off, len, tm);
+ } else if (tm.et_flags & ETF_NANOS_SET) {
+ dst[off++] = '.';
+ ftime_N(dst, off, len, tm);
+ }
+ }
+ if (index == PTIMEC_DEFAULT_FMT_INDEX && tm.et_flags & ETF_ZONE_SET) {
+ ftime_z(dst, off, len, tm);
}
dst[off] = '\0';
} else {
@@ -92,6 +105,9 @@ date_time_scanner::scan(const char* time_dest,
struct timeval& tv_out,
bool convert_local)
{
+ static const auto& cfg
+ = injector::get<const date_time_scanner_ns::config&>();
+
int curr_time_fmt = -1;
bool found = false;
const char* retval = nullptr;
@@ -100,32 +116,34 @@ date_time_scanner::scan(const char* time_dest,
time_fmt = PTIMEC_FORMAT_STR;
}
+ this->dts_zoned_to_local = cfg.c_zoned_to_local;
while (next_format(time_fmt, curr_time_fmt, this->dts_fmt_lock)) {
*tm_out = this->dts_base_tm;
tm_out->et_flags = 0;
if (time_len > 1 && time_dest[0] == '+' && isdigit(time_dest[1])) {
retval = nullptr;
- auto epoch_scan_res = scn::scan_value<int64_t>(
- scn::string_view{time_dest, time_len});
+ auto sv = scn::string_view{time_dest, time_len};
+ auto epoch_scan_res = scn::scan_value<int64_t>(sv);
if (epoch_scan_res) {
time_t gmt = epoch_scan_res.value();
- if (convert_local && this->dts_local_time) {
+ if (convert_local
+ && (this->dts_local_time || this->dts_zoned_to_local))
+ {
localtime_r(&gmt, &tm_out->et_tm);
#ifdef HAVE_STRUCT_TM_TM_ZONE
tm_out->et_tm.tm_zone = nullptr;
#endif
tm_out->et_tm.tm_isdst = 0;
- gmt = tm2sec(&tm_out->et_tm);
+ gmt = tm_out->to_timeval().tv_sec;
}
tv_out.tv_sec = gmt;
tv_out.tv_usec = 0;
tm_out->et_flags = ETF_DAY_SET | ETF_MONTH_SET | ETF_YEAR_SET
- | ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME;
+ | ETF_MACHINE_ORIENTED | ETF_EPOCH_TIME | ETF_ZONE_SET;
this->dts_fmt_lock = curr_time_fmt;
- this->dts_fmt_len = std::distance(epoch_scan_res.begin(),
- epoch_scan_res.end());
+ this->dts_fmt_len = sv.length() - epoch_scan_res.range().size();
retval = time_dest + this->dts_fmt_len;
found = true;
break;
@@ -147,10 +165,25 @@ date_time_scanner::scan(const char* time_dest,
}
if (convert_local
&& (this->dts_local_time
- || tm_out->et_flags & ETF_EPOCH_TIME))
+ || tm_out->et_flags & ETF_EPOCH_TIME
+ || ((tm_out->et_flags & ETF_ZONE_SET
+ || this->dts_default_zone != nullptr)
+ && this->dts_zoned_to_local)))
{
- time_t gmt = tm2sec(&tm_out->et_tm);
-
+ time_t gmt = tm_out->to_timeval().tv_sec;
+
+ if (!(tm_out->et_flags & ETF_ZONE_SET)
+ && !(tm_out->et_flags & ETF_EPOCH_TIME)
+ && this->dts_default_zone != nullptr)
+ {
+ date::local_seconds stime;
+ stime += std::chrono::seconds{gmt};
+ auto ztime
+ = date::make_zoned(this->dts_default_zone, stime);
+ gmt = std::chrono::duration_cast<std::chrono::seconds>(
+ ztime.get_sys_time().time_since_epoch())
+ .count();
+ }
this->to_localtime(gmt, *tm_out);
}
const auto& last_tm = this->dts_last_tm.et_tm;
@@ -167,8 +200,7 @@ date_time_scanner::scan(const char* time_dest,
tv_out.tv_sec += sec_diff;
tm_out->et_tm.tm_wday = last_tm.tm_wday;
} else {
- // log_debug("doing tm2sec");
- tv_out.tv_sec = tm2sec(&tm_out->et_tm);
+ tv_out = tm_out->to_timeval();
secs2wday(tv_out, &tm_out->et_tm);
}
tv_out.tv_usec = tm_out->et_nsec / 1000;
@@ -198,9 +230,11 @@ date_time_scanner::scan(const char* time_dest,
}
if (convert_local
&& (this->dts_local_time
- || tm_out->et_flags & ETF_EPOCH_TIME))
+ || tm_out->et_flags & ETF_EPOCH_TIME
+ || (tm_out->et_flags & ETF_ZONE_SET
+ && this->dts_zoned_to_local)))
{
- time_t gmt = tm2sec(&tm_out->et_tm);
+ time_t gmt = tm_out->to_timeval().tv_sec;
this->to_localtime(gmt, *tm_out);
#ifdef HAVE_STRUCT_TM_TM_ZONE
@@ -209,8 +243,7 @@ date_time_scanner::scan(const char* time_dest,
tm_out->et_tm.tm_isdst = 0;
}
- tv_out.tv_sec = tm2sec(&tm_out->et_tm);
- tv_out.tv_usec = tm_out->et_nsec / 1000;
+ tv_out = tm_out->to_timeval();
secs2wday(tv_out, &tm_out->et_tm);
this->dts_fmt_lock = curr_time_fmt;
@@ -234,7 +267,10 @@ date_time_scanner::scan(const char* time_dest,
if (retval != nullptr && static_cast<size_t>(retval - time_dest) < time_len)
{
/* Try to pull out the milli/micro-second value. */
- if (retval[0] == '.' || retval[0] == ',') {
+ if (!(tm_out->et_flags
+ & (ETF_MILLIS_SET | ETF_MICROS_SET | ETF_NANOS_SET))
+ && (retval[0] == '.' || retval[0] == ','))
+ {
off_t off = (retval - time_dest) + 1;
if (ptime_N(tm_out, time_dest, off, time_len)) {
@@ -243,7 +279,7 @@ date_time_scanner::scan(const char* time_dest,
std::chrono::nanoseconds{tm_out->et_nsec})
.count();
this->dts_fmt_len += 10;
- tm_out->et_flags |= ETF_NANOS_SET;
+ tm_out->et_flags |= ETF_NANOS_SET | ETF_SUB_NOT_IN_FORMAT;
retval += 10;
} else if (ptime_f(tm_out, time_dest, off, time_len)) {
tv_out.tv_usec
@@ -251,7 +287,7 @@ date_time_scanner::scan(const char* time_dest,
std::chrono::nanoseconds{tm_out->et_nsec})
.count();
this->dts_fmt_len += 7;
- tm_out->et_flags |= ETF_MICROS_SET;
+ tm_out->et_flags |= ETF_MICROS_SET | ETF_SUB_NOT_IN_FORMAT;
retval += 7;
} else if (ptime_L(tm_out, time_dest, off, time_len)) {
tv_out.tv_usec
@@ -259,7 +295,7 @@ date_time_scanner::scan(const char* time_dest,
std::chrono::nanoseconds{tm_out->et_nsec})
.count();
this->dts_fmt_len += 4;
- tm_out->et_flags |= ETF_MILLIS_SET;
+ tm_out->et_flags |= ETF_MILLIS_SET | ETF_SUB_NOT_IN_FORMAT;
retval += 4;
}
}
@@ -287,22 +323,27 @@ date_time_scanner::to_localtime(time_t t, exttm& tm_out)
if (t < this->dts_local_offset_valid || t >= this->dts_local_offset_expiry)
{
- time_t new_gmt;
-
localtime_r(&t, &tm_out.et_tm);
+ // Clear the gmtoff set by localtime_r() otherwise tm2sec() will
+ // convert the time back again.
#ifdef HAVE_STRUCT_TM_TM_ZONE
+ tm_out.et_tm.tm_gmtoff = 0;
tm_out.et_tm.tm_zone = nullptr;
#endif
tm_out.et_tm.tm_isdst = 0;
-
- new_gmt = tm2sec(&tm_out.et_tm);
- this->dts_local_offset_cache = t - new_gmt;
+ auto new_gmt = tm2sec(&tm_out.et_tm);
+ this->dts_local_offset_cache = new_gmt - t;
this->dts_local_offset_valid = t;
this->dts_local_offset_expiry = t + (EXPIRE_TIME - 1);
this->dts_local_offset_expiry
-= this->dts_local_offset_expiry % EXPIRE_TIME;
} else {
- time_t adjust_gmt = t - this->dts_local_offset_cache;
- gmtime_r(&adjust_gmt, &tm_out.et_tm);
+ time_t adjust_gmt = t + this->dts_local_offset_cache;
+ secs2tm(adjust_gmt, &tm_out.et_tm);
}
+ tm_out.et_gmtoff = 0;
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ tm_out.et_tm.tm_gmtoff = 0;
+ tm_out.et_tm.tm_zone = nullptr;
+#endif
}