@@ -355,6 +355,109 @@ Date Date::fromDbString(const std::string &datetime)
355355 static_cast <double >(timezoneOffset ()));
356356}
357357
358+ Date Date::parseDatetimeTz (const std::string &datetime)
359+ {
360+ unsigned int year = {0 }, month = {0 }, day = {0 }, hour = {0 }, minute = {0 },
361+ second = {0 }, microSecond = {0 };
362+ int tzSign{0 }, tzOffset{0 };
363+ std::vector<std::string> v = splitString (datetime, " " );
364+ if (v.empty ())
365+ {
366+ throw std::invalid_argument (" Invalid date string: " + datetime);
367+ }
368+
369+ // parse date
370+ const std::vector<std::string> date = splitString (v[0 ], " -" );
371+ if (date.size () != 3 )
372+ {
373+ throw std::invalid_argument (" Invalid date string: " + datetime);
374+ }
375+ year = std::stol (date[0 ]);
376+ month = std::stol (date[1 ]);
377+ day = std::stol (date[2 ]);
378+
379+ // only have date part
380+ if (v.size () <= 1 )
381+ {
382+ return trantor::Date{year, month, day};
383+ }
384+
385+ // check timezone without space seperated
386+ if (v.size () == 2 )
387+ {
388+ auto pos = v[1 ].find (' +' );
389+ if (pos != std::string::npos)
390+ {
391+ tzSign = 1 ;
392+ v.push_back (v[1 ].substr (pos + 1 ));
393+ v[1 ] = v[1 ].substr (0 , pos);
394+ }
395+ else if ((pos = v[1 ].find (' -' )) != std::string::npos)
396+ {
397+ tzSign = -1 ;
398+ v.push_back (v[1 ].substr (pos + 1 ));
399+ v[1 ] = v[1 ].substr (0 , pos);
400+ }
401+ }
402+
403+ // parse time
404+ std::vector<std::string> timeParts = splitString (v[1 ], " :" );
405+ if (timeParts.size () < 2 || timeParts.size () > 3 )
406+ {
407+ throw std::invalid_argument (" Invalid time string: " + datetime);
408+ }
409+ hour = std::stol (timeParts[0 ]);
410+ minute = std::stol (timeParts[1 ]);
411+ if (timeParts.size () == 3 )
412+ {
413+ auto secParts = splitString (timeParts[2 ], " ." );
414+ second = std::stol (secParts[0 ]);
415+ // micro seconds
416+ if (secParts.size () > 1 )
417+ {
418+ if (secParts[1 ].length () > 6 )
419+ {
420+ secParts[1 ].resize (6 );
421+ }
422+ else if (secParts[1 ].length () < 6 )
423+ {
424+ secParts[1 ].append (6 - secParts[1 ].length (), ' 0' );
425+ }
426+ microSecond = std::stol (secParts[1 ]);
427+ }
428+ }
429+
430+ // timezone
431+ if (v.size () >= 3 )
432+ {
433+ std::string &tz = v[2 ];
434+ if (tzSign == 0 )
435+ {
436+ if (tz[0 ] == ' -' )
437+ {
438+ tz = tz.substr (1 );
439+ tzSign = -1 ;
440+ }
441+ else
442+ {
443+ tzSign = 1 ;
444+ }
445+ }
446+
447+ auto tzParts = splitString (tz, " :" );
448+ if (tzParts.size () == 1 && tz.size () == 4 )
449+ {
450+ tzParts = {tz.substr (0 , 2 ), tz.substr (2 )}; // 0800
451+ }
452+ int tzHour = std::stoi (tzParts[0 ]);
453+ int tzMin = tzParts.size () > 1 ? std::stoi (tzParts[1 ]) : 0 ;
454+ tzOffset = tzSign * (tzHour * 3600 + tzMin * 60 );
455+ }
456+
457+ return trantor::Date (year, month, day, hour, minute, second, microSecond)
458+ .after (timezoneOffset () - tzOffset);
459+ }
460+
358461std::string Date::toCustomFormattedStringLocal (const std::string &fmtStr,
359462 bool showMicroseconds) const
360463{
0 commit comments