@@ -10,7 +10,7 @@ namespace {
1010
1111class TCsvToYdbConverter {
1212public:
13- explicit TCsvToYdbConverter (TTypeParser& parser, const TString& nullValue)
13+ explicit TCsvToYdbConverter (TTypeParser& parser, const std::optional< TString> & nullValue)
1414 : Parser(parser)
1515 , NullValue(nullValue)
1616 {
@@ -106,15 +106,30 @@ class TCsvToYdbConverter {
106106 case EPrimitiveType::DyNumber:
107107 Builder.DyNumber (token);
108108 break ;
109- case EPrimitiveType::Date:
110- Builder.Date (TInstant::Days (GetArithmetic<ui16>(token)));
109+ case EPrimitiveType::Date: {
110+ TInstant date;
111+ if (!TInstant::TryParseIso8601 (token, date)) {
112+ date = TInstant::Days (GetArithmetic<ui16>(token));
113+ }
114+ Builder.Date (date);
111115 break ;
112- case EPrimitiveType::Datetime:
113- Builder.Datetime (TInstant::Seconds (GetArithmetic<ui32>(token)));
116+ }
117+ case EPrimitiveType::Datetime: {
118+ TInstant datetime;
119+ if (!TInstant::TryParseIso8601 (token, datetime)) {
120+ datetime = TInstant::Seconds (GetArithmetic<ui32>(token));
121+ }
122+ Builder.Datetime (datetime);
114123 break ;
115- case EPrimitiveType::Timestamp:
116- Builder.Timestamp (TInstant::MicroSeconds (GetArithmetic<ui64>(token)));
124+ }
125+ case EPrimitiveType::Timestamp: {
126+ TInstant timestamp;
127+ if (!TInstant::TryParseIso8601 (token, timestamp)) {
128+ timestamp = TInstant::MicroSeconds (GetArithmetic<ui64>(token));
129+ }
130+ Builder.Timestamp (timestamp);
117131 break ;
132+ }
118133 case EPrimitiveType::Interval:
119134 Builder.Interval (GetArithmetic<i64 >(token));
120135 break ;
@@ -144,7 +159,7 @@ class TCsvToYdbConverter {
144159 }
145160 case TTypeParser::ETypeKind::Optional: {
146161 Parser.OpenOptional ();
147- if (token == NullValue) {
162+ if (NullValue && token == NullValue) {
148163 Builder.EmptyOptional (GetType ());
149164 } else {
150165 Builder.BeginOptional ();
@@ -247,13 +262,13 @@ class TCsvToYdbConverter {
247262
248263private:
249264 TTypeParser& Parser;
250- const TString NullValue = " " ;
265+ const std::optional< TString> NullValue = " " ;
251266 TValueBuilder Builder;
252267};
253268
254269}
255270
256- TCsvParser::TCsvParser (TString&& headerRow, const char delimeter, const TString& nullValue,
271+ TCsvParser::TCsvParser (TString&& headerRow, const char delimeter, const std::optional< TString> & nullValue,
257272 const std::map<TString, TType>* paramTypes,
258273 const std::map<TString, TString>* paramSources)
259274 : HeaderRow(std::move(headerRow))
@@ -266,7 +281,7 @@ TCsvParser::TCsvParser(TString&& headerRow, const char delimeter, const TString&
266281 Header = static_cast <TVector<TString>>(splitter);
267282}
268283
269- TCsvParser::TCsvParser (TVector<TString>&& header, const char delimeter, const TString& nullValue,
284+ TCsvParser::TCsvParser (TVector<TString>&& header, const char delimeter, const std::optional< TString> & nullValue,
270285 const std::map<TString, TType>* paramTypes,
271286 const std::map<TString, TString>* paramSources)
272287 : Header(std::move(header))
@@ -333,7 +348,7 @@ void TCsvParser::GetValue(TString&& data, TValueBuilder& builder, const TType& t
333348 parser.OpenStruct ();
334349 while (parser.TryNextMember ()) {
335350 TString name = parser.GetMemberName ();
336- if (name == NullValue ) {
351+ if (name == " __ydb_skip_column_name " ) {
337352 continue ;
338353 }
339354 auto fieldIt = fields.find (name);
@@ -353,7 +368,7 @@ TType TCsvParser::GetColumnsType() const {
353368 if (ParamTypes->find (colName) != ParamTypes->end ()) {
354369 builder.AddMember (colName, ParamTypes->at (colName));
355370 } else {
356- builder.AddMember (NullValue , TTypeBuilder ().Build ());
371+ builder.AddMember (" __ydb_skip_column_name " , TTypeBuilder ().Build ());
357372 }
358373 }
359374 builder.EndStruct ();
0 commit comments