aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhcpp <hcpp@ydb.tech>2022-08-05 15:39:56 +0300
committerhcpp <hcpp@ydb.tech>2022-08-05 15:39:56 +0300
commitc64c4f299ec437313284b71a45c361659c7997c0 (patch)
treedbb2d0b2ac41be943f0c6ab36ed87ad10e846ebd
parent926b1b3913a04b77d6d73f27995a3c0a71a81c03 (diff)
downloadydb-c64c4f299ec437313284b71a45c361659c7997c0.tar.gz
parse/format for datetime
-rw-r--r--ydb/library/yql/providers/s3/path_generator/yql_s3_path_generator.cpp37
1 files changed, 32 insertions, 5 deletions
diff --git a/ydb/library/yql/providers/s3/path_generator/yql_s3_path_generator.cpp b/ydb/library/yql/providers/s3/path_generator/yql_s3_path_generator.cpp
index c5bec51f401..8a869acd9d0 100644
--- a/ydb/library/yql/providers/s3/path_generator/yql_s3_path_generator.cpp
+++ b/ydb/library/yql/providers/s3/path_generator/yql_s3_path_generator.cpp
@@ -11,6 +11,33 @@ namespace NYql::NPathGenerator {
namespace {
+TInstant Strptime(const TString& input, const TString& format) {
+ struct tm inputTm;
+ memset(&inputTm, 0, sizeof(tm));
+ inputTm.tm_mday = 1;
+ if (strptime(input.data(), format.data(), &inputTm) != nullptr) {
+ const time_t seconds = TimeGM(&inputTm);
+ if (seconds != static_cast<time_t>(-1)) {
+ return TInstant::Seconds(seconds);
+ }
+ }
+ ythrow yexception() << "Can't parse date " << input << " in format " << format;
+}
+
+TString Strftime(const char* format, TInstant time) {
+ struct tm tm{};
+ time_t clock = time.Seconds();
+ localtime_r(&clock, &tm);
+ size_t size = Max<size_t>(strlen(format) * 2 + 1, 107);
+ TTempBuf buf(size);
+ int r = strftime(buf.Data(), buf.Size(), format, &tm);
+ if (r != 0) {
+ return TString(buf.Data(), r);
+ }
+ ythrow yexception() << "Can't format date " << time << " in format " << format;
+}
+
+
void ReplaceAll(TString& str, const TString& from, const TString& to) {
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != TString::npos) {
@@ -213,8 +240,8 @@ public:
return fmtInteger(config.Digits, value);
}
case IPathGenerator::EType::DATE: {
- TInstant time = TInstant::Zero() /* ToInstant(dataValue) */;
- return time.FormatLocalTime(config.Format.c_str());
+ TInstant time = TInstant::ParseIso8601(dataValue);
+ return Strftime(config.Format.c_str(), time);
}
break;
}
@@ -244,8 +271,8 @@ public:
return std::to_string(value);
}
case IPathGenerator::EType::DATE: {
- TInstant time = TInstant::Zero() /* ToInstant(dataValue) */;
- return time.FormatLocalTime(config.Format.c_str());
+ TInstant time = Strptime(TString{pathValue}, config.Format);
+ return time.ToStringLocal();
}
break;
}
@@ -500,7 +527,7 @@ private:
const TDuration interval = FromUnit(rule.Interval, rule.IntervalUnit);
for (TInstant current = ParseDate(rule.From, now); current <= to; current += interval) {
TString copyLocationTemplate = locationTemplate;
- const TString time = current.FormatLocalTime(rule.Format.c_str());
+ const TString time = Strftime(rule.Format.c_str(), current);
ReplaceAll(copyLocationTemplate, "${" + rule.Name + "}", time);
columnsWithValue.push_back(TColumnWithValue{.Name=rule.Name, .Type=NUdf::EDataSlot::String, .Value=time});
DoGenerate(rules, copyLocationTemplate, columnsWithValue, result, pathsLimit, now, p + 1);