You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确将struct timespec转换为struct timeval?

解决struct timespec转struct timeval适配lutimes()的EINVAL问题

我之前在处理文件时间戳转换时也踩过这个坑,咱们先把问题拆解清楚:

你遇到的EINVAL错误核心原因很明确——转换后的struct timeval里tv_usec超出了0 <= tv_usec < 1000000的范围,而根源是你拿到的struct timespec本身可能存在纳秒值超过999,999,999的情况(比如你用touch调试发现的tv_sec=0但tv_nsec>1e9)。

正确的转换逻辑

struct timespec的tv_nsec规范范围是0~999,999,999,但实际场景中可能出现超出这个范围的值(比如相对时间计算、某些系统调用返回的异常值)。转换时必须先处理纳秒的进位,再转成微秒:

  • 把超出1e9的纳秒部分转换成秒,加到tv_sec上
  • 剩余的纳秒值取模1e9,确保在合法范围内
  • 将剩余纳秒除以1000,得到微秒值赋值给tv_usec
  • 额外处理负数情况(如果是负的相对时间)

代码实现示例

#include <sys/time.h>
#include <time.h>

void timespec_to_timeval(const struct timespec *ts, struct timeval *tv) {
    // 先处理纳秒的进位,把超过1e9的部分转成秒
    time_t total_sec = ts->tv_sec + ts->tv_nsec / 1000000000;
    long remaining_nsec = ts->tv_nsec % 1000000000;

    // 处理负数纳秒的情况(比如ts是负的偏移量)
    if (remaining_nsec < 0) {
        total_sec -= 1;
        remaining_nsec += 1000000000;
    }

    // 赋值给timeval结构体
    tv->tv_sec = total_sec;
    tv->tv_usec = remaining_nsec / 1000; // 纳秒转微秒
}

针对你场景的验证

比如你遇到的tv_sec=0、tv_nsec=1500000000的情况:

  • 转换后total_sec = 0 + 1500000000 / 1e9 = 1
  • remaining_nsec = 1500000000 % 1e9 = 500000000
  • tv_usec = 500000000 / 1000 = 500000

这个结果完全符合struct timeval的规范,传给lutimes()就不会再返回EINVAL错误了。

内容的提问来源于stack exchange,提问作者Cobra_Fast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:33:45