diff options
Diffstat (limited to '')
-rw-r--r-- | src/base/date_time_scanner.cc | 117 |
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 } |