@@ -323,6 +323,109 @@ Date Date::fromDbString(const std::string &datetime)
323323 static_cast <double >(timezoneOffset ()));
324324}
325325
326+ Date Date::parseDatetimeTz (const std::string &datetime)
327+ {
328+ unsigned int year = {0 }, month = {0 }, day = {0 }, hour = {0 }, minute = {0 },
329+ second = {0 }, microSecond = {0 };
330+ int tzSign{0 }, tzOffset{0 };
331+ std::vector<std::string> v = splitString (datetime, " " );
332+ if (v.empty ())
333+ {
334+ throw std::invalid_argument (" Invalid date string: " + datetime);
335+ }
336+
337+ // parse date
338+ const std::vector<std::string> date = splitString (v[0 ], " -" );
339+ if (date.size () != 3 )
340+ {
341+ throw std::invalid_argument (" Invalid date string: " + datetime);
342+ }
343+ year = std::stol (date[0 ]);
344+ month = std::stol (date[1 ]);
345+ day = std::stol (date[2 ]);
346+
347+ // only have date part
348+ if (v.size () <= 1 )
349+ {
350+ return trantor::Date{year, month, day};
351+ }
352+
353+ // check timezone without space seperated
354+ if (v.size () == 2 )
355+ {
356+ auto pos = v[1 ].find (' +' );
357+ if (pos != std::string::npos)
358+ {
359+ tzSign = 1 ;
360+ v.push_back (v[1 ].substr (pos + 1 ));
361+ v[1 ] = v[1 ].substr (0 , pos);
362+ }
363+ else if ((pos = v[1 ].find (' -' )) != std::string::npos)
364+ {
365+ tzSign = -1 ;
366+ v.push_back (v[1 ].substr (pos + 1 ));
367+ v[1 ] = v[1 ].substr (0 , pos);
368+ }
369+ }
370+
371+ // parse time
372+ std::vector<std::string> timeParts = splitString (v[1 ], " :" );
373+ if (timeParts.size () < 2 || timeParts.size () > 3 )
374+ {
375+ throw std::invalid_argument (" Invalid time string: " + datetime);
376+ }
377+ hour = std::stol (timeParts[0 ]);
378+ minute = std::stol (timeParts[1 ]);
379+ if (timeParts.size () == 3 )
380+ {
381+ auto secParts = splitString (timeParts[2 ], " ." );
382+ second = std::stol (secParts[0 ]);
383+ // micro seconds
384+ if (secParts.size () > 1 )
385+ {
386+ if (secParts[1 ].length () > 6 )
387+ {
388+ secParts[1 ].resize (6 );
389+ }
390+ else if (secParts[1 ].length () < 6 )
391+ {
392+ secParts[1 ].append (6 - secParts[1 ].length (), ' 0' );
393+ }
394+ microSecond = std::stol (secParts[1 ]);
395+ }
396+ }
397+
398+ // timezone
399+ if (v.size () >= 3 )
400+ {
401+ std::string &tz = v[2 ];
402+ if (tzSign == 0 )
403+ {
404+ if (tz[0 ] == ' -' )
405+ {
406+ tz = tz.substr (1 );
407+ tzSign = -1 ;
408+ }
409+ else
410+ {
411+ tzSign = 1 ;
412+ }
413+ }
414+
415+ auto tzParts = splitString (tz, " :" );
416+ if (tzParts.size () == 1 && tz.size () == 4 )
417+ {
418+ tzParts = {tz.substr (0 , 2 ), tz.substr (2 )}; // 0800
419+ }
420+ int tzHour = std::stoi (tzParts[0 ]);
421+ int tzMin = tzParts.size () > 1 ? std::stoi (tzParts[1 ]) : 0 ;
422+ tzOffset = tzSign * (tzHour * 3600 + tzMin * 60 );
423+ }
424+
425+ return trantor::Date (year, month, day, hour, minute, second, microSecond)
426+ .after (timezoneOffset () - tzOffset);
427+ }
428+
326429std::string Date::toCustomFormattedStringLocal (const std::string &fmtStr,
327430 bool showMicroseconds) const
328431{
0 commit comments