> ## Documentation Index
> Fetch the complete documentation index at: https://bun.ll1025.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 日期和时间

> 了解如何在 Bun 测试中使用 setSystemTime 和 Jest 兼容函数操作时间和日期

`bun:test` 允许你在测试中更改当前时间。

这适用于以下任何内容：

* `Date.now`
* `new Date()`
* `new Intl.DateTimeFormat().format()`

## setSystemTime

要更改系统时间，请使用 `setSystemTime`：

```ts title="test.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
import { setSystemTime, beforeAll, test, expect } from "bun:test";

beforeAll(() => {
  setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
});

test("现在是 2020 年", () => {
  expect(new Date().getFullYear()).toBe(2020);
});
```

Jest 的 `useFakeTimers` 和 `useRealTimers` 也受支持，因此使用它们的现有测试可以继续正常工作：

```ts title="test.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
test("就像在 jest 中一样", () => {
  jest.useFakeTimers();
  jest.setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
  expect(new Date().getFullYear()).toBe(2020);
  jest.useRealTimers();
  expect(new Date().getFullYear()).toBeGreaterThan(2020);
});

test("与 jest 不同", () => {
  const OriginalDate = Date;
  jest.useFakeTimers();
  if (typeof Bun === "undefined") {
    // 在 Jest 中，Date 构造函数会改变
    // 这可能导致各种 bug，因为突然 Date !== 测试前的 Date
    expect(Date).not.toBe(OriginalDate);
    expect(Date.now).not.toBe(OriginalDate.now);
  } else {
    // 在 bun:test 中，使用 useFakeTimers 时 Date 构造函数不会改变
    expect(Date).toBe(OriginalDate);
    expect(Date.now).toBe(OriginalDate.now);
  }
});
```

## 重置系统时间

要重置系统时间，不传参数给 `setSystemTime`：

```ts title="test.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
import { setSystemTime, expect, test } from "bun:test";

test("曾经是 2020 年，只是片刻。", () => {
  // 设置时间！
  setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
  expect(new Date().getFullYear()).toBe(2020);

  // 重置！
  setSystemTime();

  expect(new Date().getFullYear()).toBeGreaterThan(2020);
});
```

## 使用 jest.now() 获取模拟时间

当时间被模拟时（使用 `setSystemTime` 或 `useFakeTimers`），`jest.now()` 返回当前模拟的时间戳：

```ts title="test.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
import { test, expect, jest } from "bun:test";

test("获取当前模拟时间", () => {
  jest.useFakeTimers();
  jest.setSystemTime(new Date("2020-01-01T00:00:00.000Z"));

  expect(Date.now()).toBe(1577836800000); // 2020 年 1 月 1 日的时间戳
  expect(jest.now()).toBe(1577836800000); // 相同的值

  jest.useRealTimers();
});
```

使用它可以在不创建新的 `Date` 对象的情况下读取模拟时间。

## 设置时区

默认情况下，`bun test` 在 UTC（`Etc/UTC`）中运行。要更改时区，可以向 `bun test` 传递 `TZ` 环境变量：

```bash terminal icon="terminal" theme={null}
TZ=America/Los_Angeles bun test
```

或者在运行时设置 `process.env.TZ`：

```ts title="test.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
import { test, expect } from "bun:test";

test("欢迎来到加州！", () => {
  process.env.TZ = "America/Los_Angeles";
  expect(new Date().getTimezoneOffset()).toBe(420);
  expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe("America/Los_Angeles");
});

test("欢迎来到纽约！", () => {
  // 与 Jest 不同，你可以在运行时多次设置时区，它会正常工作。
  process.env.TZ = "America/New_York";
  expect(new Date().getTimezoneOffset()).toBe(240);
  expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe("America/New_York");
});
```

<Info>与 Jest 不同，你可以在运行时多次更改时区。</Info>
