JS 获取今天零点并前后偏移 N 小时:Date setHours 与时区格式化

获取今天零点

const now = new Date();
const midnight = new Date(now);
midnight.setHours(0, 0, 0, 0);

console.log(midnight);
// Mon Apr 14 2026 00:00:00 GMT+0800

setHours(0, 0, 0, 0) 四个参数分别是小时、分钟、秒、毫秒,全设为 0 就是当天零点(本地时间)。

往后推 N 小时

const now = new Date();
const start = new Date(now);
start.setHours(0, 0, 0, 0);

const N = 10000;
const end = new Date(start.getTime() + N * 60 * 60 * 1000);

console.log("开始:", start);
console.log("结束:", end);
// 10000 小时 ≈ 416 天 + 16 小时后

往前推 N 小时

const before = new Date(start.getTime() - N * 60 * 60 * 1000);

console.log("今天零点:", start);
console.log("往前 10000 小时:", before);
// 约 416 天前

时区问题:toISOString() 是 UTC

console.log(start.toISOString());
// "2026-04-13T16:00:00.000Z"  ← UTC 时间,比北京时间少 8 小时

toISOString() 始终输出 UTC 时间。中国时区(UTC+8)的零点在 UTC 是前一天 16:00,如果直接用这个输出给后端或用于显示会有偏差。

本地时间格式化:

function formatLocal(date) {
  return [
    date.getFullYear(),
    String(date.getMonth() + 1).padStart(2, "0"),
    String(date.getDate()).padStart(2, "0")
  ].join("-") + " " + [
    String(date.getHours()).padStart(2, "0"),
    String(date.getMinutes()).padStart(2, "0"),
    String(date.getSeconds()).padStart(2, "0")
  ].join(":");
}

console.log(formatLocal(start));  // "2026-04-14 00:00:00"
console.log(formatLocal(end));    // "2027-06-30 16:00:00"

生成时间序列

K 线拉取、回测等场景需要每小时一个时间点的数组:

function generateHourlyRange(startDate, hours) {
  const step = 60 * 60 * 1000;
  const arr = [];

  for (let i = 0; i <= hours; i++) {
    arr.push(new Date(startDate.getTime() + i * step));
  }

  return arr;
}

const start = new Date();
start.setHours(0, 0, 0, 0);

const range = generateHourlyRange(start, 24);
console.log(range.slice(0, 3).map(formatLocal));
// ["2026-04-14 00:00:00", "2026-04-14 01:00:00", "2026-04-14 02:00:00"]

往前推的时间序列只需把 + i * step 改成 - i * step

与后端接口对接

如果后端接受的是 Unix 时间戳(秒):

const startTs = Math.floor(start.getTime() / 1000);
const endTs = Math.floor(end.getTime() / 1000);

fetch(`/api/kline?start=${startTs}&end=${endTs}`)

如果后端接受 ISO 字符串(UTC):

const params = new URLSearchParams({
  start: start.toISOString(),
  end: end.toISOString()
});

两者都是基于 getTime() 的毫秒时间戳,不存在时区歧义,只是显示层面需要处理本地时区。