如何用strptime解析纳秒级RFC3339时间戳?(适用于C/Python)
标准解析方法:拆分字符串分阶段处理
这是个很常见的痛点——毕竟strptime()(不管是C标准库还是Python调用的C底层实现)的标准格式符里确实没有直接支持纳秒的选项。不过没关系,我们可以用拆分字符串、分阶段解析再合并的方法来解决,这是最通用的标准方案,对两种语言都适用。
核心思路
你给出的时间戳格式是"YYYY-MM-DD HH:MM:SS.NNNNNNNNN±HH:MM",我们可以把它拆成三个独立部分分别处理:
- 秒级日期时间:
YYYY-MM-DD HH:MM:SS——这部分完全可以用strptime直接解析 - 纳秒值:
NNNNNNNNN——手动提取后转换为整数即可 - 时区偏移:
±HH:MM——多数现代系统的strptime支持用%z格式符解析(C的话可能需要GNU扩展,不过现在主流平台都默认支持了)
C语言实现示例
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> int main() { const char *timestamp = "2019-12-06 13:02:21.711339765+05:30"; struct tm tm_data; char nanosec_str[10]; long nanosec; char tz_str[6]; time_t epoch_sec; struct timespec ts; // 拆分并提取秒级时间、纳秒、时区部分 if (sscanf(timestamp, "%d-%d-%d %d:%d:%d.%9[0-9]%5s", &tm_data.tm_year, &tm_data.tm_mon, &tm_data.tm_mday, &tm_data.tm_hour, &tm_data.tm_min, &tm_data.tm_sec, nanosec_str, tz_str) != 8) { fprintf(stderr, "Failed to split timestamp format\n"); return 1; } // 调整tm结构的年份和月份(tm_year从1900开始计数,tm_mon从0开始) tm_data.tm_year -= 1900; tm_data.tm_mon -= 1; tm_data.tm_isdst = -1; // 让系统自动判断夏令时状态 // 解析时区偏移(依赖strptime的%z扩展,主流GNU系统默认支持) strptime(tz_str, "%z", &tm_data); // 转换为epoch秒数 epoch_sec = mktime(&tm_data); if (epoch_sec == -1) { fprintf(stderr, "Failed to convert to epoch timestamp\n"); return 1; } // 把纳秒字符串转为整数 nanosec = strtol(nanosec_str, NULL, 10); // 填充timespec结构,同时存储秒和纳秒 ts.tv_sec = epoch_sec; ts.tv_nsec = nanosec; // 验证输出 printf("Epoch seconds: %ld\n", ts.tv_sec); printf("Nanoseconds: %ld\n", ts.tv_nsec); return 0; }
Python实现示例
Python 3.6+的datetime原生支持纳秒,我们用正则拆分更稳妥(兼容正负时区):
import re from datetime import datetime, timedelta timestamp = "2019-12-06 13:02:21.711339765+05:30" # 用正则匹配拆分各部分 match = re.match(r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\.(\d{9})([+-]\d{2}:\d{2})', timestamp) if not match: raise ValueError("Invalid timestamp format") sec_part, nanosec_part, tz_part = match.groups() # 解析秒级日期时间和时区 dt = datetime.strptime(f"{sec_part}{tz_part}", "%Y-%m-%d %H:%M:%S%z") # 转换纳秒字符串为整数 nanosec = int(nanosec_part) # 将纳秒合并到datetime对象中 dt_with_nano = dt.replace(microsecond=nanosec//1000, nanosecond=nanosec%1000) # 验证输出 print(f"Parsed datetime with nanoseconds: {dt_with_nano}")
注意事项
- C语言中,如果你的平台不支持
strptime的%z选项,可以手动解析时区偏移:把±HH:MM拆成符号、小时、分钟,计算总偏移秒数后,调整epoch_sec得到UTC时间。 - 若使用Python 3.6之前的版本,
datetime不支持纳秒,可以只保留微秒精度(取纳秒的前6位),核心拆分思路依然适用。
内容的提问来源于stack exchange,提问作者RandomB
相关产品推荐
相关产品推荐

