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

JS字符串时间比较问题:时区偏移导致日期差值计算错误

问题描述

我开发了一款验证应用,流程是用户拍摄自拍后通过HTML表单上传至Node.js+Express.js+Formidable.js服务器,其中一项核心检测要求:自拍拍摄时间与上传时间的间隔不得超过120秒。

当前遇到的问题:

  • 从照片EXIF元数据中获取的拍摄时间格式为 2023:09:03 16:48:55,这是设备本地时间
  • 上传时间通过表单隐藏字段lt在提交时设置为new Date(),返回格式为Sun Sep 03 2023 16:49:12 GMT+1000 (Australian Eastern Standard Time)(用户使用同一设备拍摄并上传)
  • 计算时间差时,预期差值约17秒,但实际得到约-600分钟的错误结果,根源是时区偏移导致的时间解析不一致

现有计算代码:

function parseDate(s) {
  var b = s.split(/\D/);
  return new Date(b[0], b[1] - 1, b[2], b[3], b[4], b[5]);
}

console.log(exifData.exif.CreateDate);

CreateDate = parseDate(exifData.exif.CreateDate);

console.log(CreateDate);

console.log(fields.lt[0]);

submitDate = new Date(fields.lt[0]);

console.log(submitDate);

age = (submitDate - CreateDate) / (1000 * 60);

console.log(age);

/*
输出结果:
2023:09:03 16:48:55
2023-09-03T16:48:55.000Z
Sun Sep 03 2023 16:49:12 GMT+1000 (Australian Eastern Standard Time)
2023-09-03T06:49:12.000Z
-599.7166666666667 
*/
解决方案

核心问题是EXIF时间解析时未匹配设备时区:EXIF的CreateDate是设备本地时间,但现有代码解析时被默认当作UTC时间;而上传时间的Date对象是带时区的本地时间,两者时区不统一导致差值计算错误。

推荐以下两种可靠解决方法:

方法1:用时间戳传递上传时间(最简洁可靠)

直接在前端传递UTC时间戳,避免字符串解析的时区歧义:

前端修改表单提交事件

<form action="/selfie" enctype="multipart/form-data" method="post" name="fselfie">
    <input type="file" name="selfie" multiple="false" />
    <input type="hidden" name="lt" id="lt" value="" />
    <!--ADD FIELDS--> 
    <input type="submit" value="Upload" onclick="document.fselfie.lt.value = Date.now();" />
</form>

Date.now()返回的是UTC时间的毫秒级时间戳,无时区问题。

后端计算时间差

// 解析上传时间戳为Date对象
const submitDate = new Date(Number(fields.lt[0]));

// 解析EXIF本地时间为对应时区的Date对象
function parseLocalExifDate(s) {
  const [dateStr, timeStr] = s.split(' ');
  const [year, month, day] = dateStr.split(':').map(Number);
  const [hour, minute, second] = timeStr.split(':').map(Number);
  // 传入年/月/日/时/分/秒参数时,Date构造函数默认使用本地时区
  return new Date(year, month - 1, day, hour, minute, second);
}

const createDate = parseLocalExifDate(exifData.exif.CreateDate);

// 计算秒数差(取绝对值避免顺序问题)
const diffSeconds = Math.abs(submitDate - createDate) / 1000;

// 验证是否符合要求
if (diffSeconds > 120) {
  console.log("自拍拍摄时间超过120秒限制");
} else {
  console.log("自拍时间符合要求");
}

方法2:统一转换为UTC时间计算

如果必须保留字符串传递上传时间,可以通过时区偏移将EXIF时间转换为UTC时间,再与上传时间的UTC值对比:

// 解析上传时间
const submitDate = new Date(fields.lt[0]);
// 获取设备时区偏移(单位:分钟,UTC - 本地时间)
const timeZoneOffset = submitDate.getTimezoneOffset();

// 解析EXIF本地时间并转换为UTC时间
function parseExifToUTC(s, offsetMinutes) {
  const [dateStr, timeStr] = s.split(' ');
  const [year, month, day] = dateStr.split(':').map(Number);
  const [hour, minute, second] = timeStr.split(':').map(Number);
  // 先创建本地时间的Date对象
  const localDate = new Date(year, month - 1, day, hour, minute, second);
  // 转换为UTC时间戳:本地时间戳 - 时区偏移对应的毫秒数
  const utcTimestamp = localDate.getTime() + (offsetMinutes * 60 * 1000);
  return new Date(utcTimestamp);
}

const createDateUTC = parseExifToUTC(exifData.exif.CreateDate, timeZoneOffset);
const submitDateUTC = new Date(submitDate.toUTCString());

// 计算秒数差
const diffSeconds = Math.abs(submitDateUTC - createDateUTC) / 1000;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:55:54