@@ -56,12 +56,27 @@ std::string timestamp_to_string(uint64_t timestamp_ms) {
5656uint64_t to_milliseconds (const std::string &iso_str) {
5757 // Parse ISO 8601 format: "YYYY-MM-DDTHH:MM:SS.sssZ"
5858 std::tm tm = {};
59- int milliseconds = 0 ;
60-
61- // Parse the date and time parts
62- std::sscanf (iso_str.c_str (), " %d-%d-%dT%d:%d:%d.%d" ,
63- &tm.tm_year , &tm.tm_mon , &tm.tm_mday ,
64- &tm.tm_hour , &tm.tm_min , &tm.tm_sec , &milliseconds);
59+ double fractional_seconds = 0.0 ;
60+
61+ // Find the decimal point position
62+ size_t dot_pos = iso_str.find (' .' );
63+ if (dot_pos != std::string::npos) {
64+ // Parse base timestamp
65+ std::sscanf (iso_str.c_str (), " %d-%d-%dT%d:%d:%d" ,
66+ &tm.tm_year , &tm.tm_mon , &tm.tm_mday ,
67+ &tm.tm_hour , &tm.tm_min , &tm.tm_sec );
68+
69+ // Extract fractional seconds (e.g., ".718887" -> 0.718887)
70+ size_t end_pos = iso_str.find_first_of (" Z+" , dot_pos);
71+ if (end_pos == std::string::npos) end_pos = iso_str.length ();
72+ std::string frac_str = " 0" + iso_str.substr (dot_pos, end_pos - dot_pos);
73+ fractional_seconds = std::stod (frac_str);
74+ } else {
75+ // No fractional seconds
76+ std::sscanf (iso_str.c_str (), " %d-%d-%dT%d:%d:%d" ,
77+ &tm.tm_year , &tm.tm_mon , &tm.tm_mday ,
78+ &tm.tm_hour , &tm.tm_min , &tm.tm_sec );
79+ }
6580
6681 tm.tm_year -= 1900 ; // tm_year is years since 1900
6782 tm.tm_mon -= 1 ; // tm_mon is 0-11
@@ -75,21 +90,88 @@ uint64_t to_milliseconds(const std::string &iso_str) {
7590#endif
7691
7792 // Convert to milliseconds and add the fractional part
93+ uint64_t milliseconds = static_cast <uint64_t >(fractional_seconds * 1000.0 );
7894 return static_cast <uint64_t >(time) * 1000 + milliseconds;
7995}
8096
97+ uint64_t to_microseconds (const std::string &iso_str) {
98+ // Parse ISO 8601 format: "YYYY-MM-DDTHH:MM:SS.ssssssZ"
99+ std::tm tm = {};
100+ double fractional_seconds = 0.0 ;
101+
102+ // Find the decimal point position
103+ size_t dot_pos = iso_str.find (' .' );
104+ if (dot_pos != std::string::npos) {
105+ // Parse base timestamp
106+ int parsed = std::sscanf (iso_str.c_str (), " %d-%d-%dT%d:%d:%d" ,
107+ &tm.tm_year , &tm.tm_mon , &tm.tm_mday ,
108+ &tm.tm_hour , &tm.tm_min , &tm.tm_sec );
109+
110+ if (parsed < 6 ) {
111+ return 0 ;
112+ }
113+
114+ // Extract fractional seconds (e.g., ".718887" -> 0.718887)
115+ size_t end_pos = iso_str.find_first_of (" Z+" , dot_pos);
116+ if (end_pos == std::string::npos) end_pos = iso_str.length ();
117+ std::string frac_str = " 0" + iso_str.substr (dot_pos, end_pos - dot_pos);
118+ fractional_seconds = std::stod (frac_str);
119+ } else {
120+ // No fractional seconds
121+ int parsed = std::sscanf (iso_str.c_str (), " %d-%d-%dT%d:%d:%d" ,
122+ &tm.tm_year , &tm.tm_mon , &tm.tm_mday ,
123+ &tm.tm_hour , &tm.tm_min , &tm.tm_sec );
124+ if (parsed < 6 ) {
125+ return 0 ;
126+ }
127+ }
128+
129+ tm.tm_year -= 1900 ; // tm_year is years since 1900
130+ tm.tm_mon -= 1 ; // tm_mon is 0-11
131+ tm.tm_isdst = 0 ; // Not daylight saving time
132+
133+ // Convert to time_t (seconds since epoch, UTC)
134+ #ifdef _WIN32
135+ auto time = _mkgmtime (&tm);
136+ #else
137+ auto time = timegm (&tm);
138+ #endif
139+
140+ // Convert to microseconds and add the fractional part
141+ uint64_t microseconds = static_cast <uint64_t >(fractional_seconds * 1000000.0 );
142+ return static_cast <uint64_t >(time) * 1000000ULL + microseconds;
143+ }
144+
81145uint64_t to_nanoseconds (const std::string &iso_str) {
82146 // Parse ISO 8601 format: "YYYY-MM-DDTHH:MM:SS.sssssssssZ"
83147 std::tm tm = {};
84- int nanoseconds = 0 ;
85-
86- // Parse the date and time parts
87- int parsed = std::sscanf (iso_str.c_str (), " %d-%d-%dT%d:%d:%d.%d" ,
88- &tm.tm_year , &tm.tm_mon , &tm.tm_mday ,
89- &tm.tm_hour , &tm.tm_min , &tm.tm_sec , &nanoseconds);
148+ double fractional_seconds = 0.0 ;
149+
150+ // Find the decimal point position
151+ size_t dot_pos = iso_str.find (' .' );
152+ if (dot_pos != std::string::npos) {
153+ // Parse base timestamp
154+ int parsed = std::sscanf (iso_str.c_str (), " %d-%d-%dT%d:%d:%d" ,
155+ &tm.tm_year , &tm.tm_mon , &tm.tm_mday ,
156+ &tm.tm_hour , &tm.tm_min , &tm.tm_sec );
157+
158+ if (parsed < 6 ) {
159+ return 0 ;
160+ }
90161
91- if (parsed < 6 ) {
92- return 0 ;
162+ // Extract fractional seconds (e.g., ".718887475" -> 0.718887475)
163+ size_t end_pos = iso_str.find_first_of (" Z+" , dot_pos);
164+ if (end_pos == std::string::npos) end_pos = iso_str.length ();
165+ std::string frac_str = " 0" + iso_str.substr (dot_pos, end_pos - dot_pos);
166+ fractional_seconds = std::stod (frac_str);
167+ } else {
168+ // No fractional seconds
169+ int parsed = std::sscanf (iso_str.c_str (), " %d-%d-%dT%d:%d:%d" ,
170+ &tm.tm_year , &tm.tm_mon , &tm.tm_mday ,
171+ &tm.tm_hour , &tm.tm_min , &tm.tm_sec );
172+ if (parsed < 6 ) {
173+ return 0 ;
174+ }
93175 }
94176
95177 tm.tm_year -= 1900 ; // tm_year is years since 1900
@@ -104,6 +186,7 @@ uint64_t to_nanoseconds(const std::string &iso_str) {
104186#endif
105187
106188 // Convert to nanoseconds and add the fractional part
189+ uint64_t nanoseconds = static_cast <uint64_t >(fractional_seconds * 1000000000.0 );
107190 return static_cast <uint64_t >(time) * 1000000000ULL + nanoseconds;
108191}
109192
0 commit comments