全栈 JavaScript 开发人员处理日期和时间的指南
目录
介绍
时间在我们的生活中扮演着至关重要的角色。因此,作为开发人员,我们经常与日期和时间打交道。世界各地的人们都在使用计算机软件,而不同地区的时间可能有所不同。而且,我们通常在构建软件时捕获并处理各种数据记录和事件的日期和时间。因此,了解与日期和时间相关的各种细微差别至关重要。
日期格式
日期和时间可以用多种不同的格式表示。在乌克兰,日期通常以“DD-MM-YYYY”(日在前)的格式书写,而在美国,常见的格式是“MM-DD-YYYY”(月在前)。
时区
根据地理区域或政治单位(例如国家/地区),时区可能会有所不同。例如,夏季,基辅的时间为 21:00,而纽约的时间为 14:00(减 7 小时)。另外,值得一提的是,特定国家/地区的时区选择/定义可能会受到政治决策的影响。一个国家/地区可以选择与该国实际地理位置的 UTC 时差不同的 UTC 时差。
所有时区均定义为与协调世界时 (UTC) 的偏移量,范围从 UTC-12:00 到 UTC+14:00。UTC 的地理参考点是本初子午线(经度 = 0°),它穿过位于英国伦敦格林威治的皇家天文台。
此外,世界各地都有人实行夏令时 (DST),也就是夏令时。在气候温暖的月份,人们会将时钟从标准时间拨快一小时,以便在我们通常清醒的时间获得更多的日照。例如,在乌克兰,我们会在三月的最后一个星期日凌晨 3:00 将时钟拨快一小时,并在十月的最后一个星期日凌晨 4:00 恢复标准时间(将时钟拨回一小时)。夏令时的开始和结束日期取决于各个国家或政治单位(例如欧盟)。
此外,一个行政区域的时区偏移量和/或夏令时开始和结束的日期和时间可能在历史上的某个时刻发生过变化。因此,存在许多数据库来跟踪时区变化的信息。最常用的是IANA(时区数据库),也称为tz或zoneinfo。操作系统和其他计算机软件使用这些数据库进行时区处理和转换。
Unix时间戳
在计算机编程中,表示日期和时间值的常用格式是 Unix 时间戳,它是 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)与另一个日期(例如 1620758838)之间的秒数。正整数表示 Unix 纪元之后的日期,而负整数表示 Unix 纪元之前的日期。
Unix 时间戳是操作系统和数据库中存储日期和时间的常用格式之一。
在 Wikipedia 上了解有关 Unix 时间戳的更多信息:Unix 时间。
日期对象
从根本上讲,JavaScript 日期被指定为自 1970 年 1 月 1 日 00:00:00 UTC 时间起的毫秒数。该数字看起来类似于 Unix 时间戳。区别在于,Unix 时间戳是自 Unix 纪元以来的秒数,而在 JavaScript 中则是毫秒数。
在 JavaScript 中,我们使用 Date 对象来处理日期和时间:
const date = new Date();
Date 对象内部保存的是 UTC 格式的当前日期和时间。然而,默认情况下,当我们输出日期和时间时,Date 对象会将输出转换为本地时区,即 JavaScript 代码运行环境的时区(例如浏览器、Node.js 等)。
当不带参数实例化时,日期对象保存当前日期和时间(new Date()
保存当前日期)。
我们可以在 Date 的构造函数中或实例化之后设置日期和时间:
let currentDate = new Date();
let someDate = new Date('December 12, 2020 18:30:01');
let someDate = new Date('2021-12-12T18:30:01');
let someDate = new Date(2021, 11, 12, 18, 30, 1); // Month's index is zero-based
let someDate = new Date(1639326601000); // Number of milliseconds from Jan 1, 1970 00:00:00 UTC
toString
当我们实例化 Date 类时,指定的日期会在内部转换为 UTC 并进行跟踪。但是,当我们使用基本方法(例如、toLocaleString
、等)访问日期时,getHours
返回的日期将采用本地时区:
const myDate = new Date('11 May 2021 18:30:01 UTC');
console.log(myDate);
// Tue May 11 2021 21:30:01 GMT+0300 (Eastern European Summer Time)
console.log(myDate.getHours());
// 21, not 18 as you might have expected
这里我们实例化了 Date 类,并指定了 UTC 格式的日期,但打印实例化的日期对象时,得到的却是本地时区的日期,对我来说是 UTC+03:00(东欧夏令时)。所以,日期在内部是以 UTC 格式存储的,但当我们使用基本方法访问该日期时,它会被转换为本地时区。
Date 对象最流行的方法是:
Date.now();
// number of milliseconds since the Unix Epoch
new Date().getTime();
// same
Date.UTC(2021, 4, 14, 0, 0, 0);
// number of milliseconds since the Unix epoch until the specified date
const dateBasedOnUTC = new Date(
Date.UTC(2021, 4, 14, 0, 0, 0)
);
const date = new Date();
// Access and modify the date based on local time zone:
date.getFullYear(); // for example, 2021
date.setFullYear(2021);
date.getMonth(); // zero-based month index (0 - 11)
date.setMonth(0);
date.getDate(); // day of the month (1 - 31)
date.setDate(28);
date.getHours(); // 0 - 23
date.setHours(23);
date.getMinutes(); // 0 - 59
date.setMinutes(8);
date.getSeconds(); // 0 - 59
date.setSeconds(59);
// Access and modify the date based on UTC:
date.getUTCFullYear();
date.setUTCFullYear(2021);
date.getUTCMonth();
date.setUTCMonth(11);
date.getUTCDate();
date.setUTCDate(12);
date.getUTCHours();
date.setUTCHours(9);
date.getUTCMinutes();
date.setUTCMinutes(0);
date.getUTCSeconds();
date.setUTCSeconds(0);
// Other useful methods:
date.toISOString();
// Get the date string in simplified extended ISO format (ISO 8601)
date.toLocaleString('uk', { timeZone: 'UTC' });
// Get the date string in the format according to a given locale and various options
date.toLocaleString('en', { month: 'long' });
// Get the name of the month in a given locale (e.g., June, July, etc)
在 MDN Web 文档上了解有关 Date 对象的更多信息:日期
计算日期之间的差异
const date1 = new Date(Date.UTC(2021, 4, 11, 0, 0, 0));
const date2 = new Date(Date.UTC(2021, 4, 12, 0, 0, 0));
const diffInMilliseconds = date2 - date1;
const diffInHours = diffInMilliseconds / 1000 / 60 / 60;
console.log(diffInHours); // 24
在这里,我们创建两个日期对象,2021 年 5 月 11 日和 2021 年 5 月 12 日。然后,我们date1
从 2021 年 5 月 12 日()中减去 2021 年 5 月 11 日(date2
),得到 24 小时的差值。
使用日期对象时,请考虑这些日期对象实例化时所处的时区。请看另一个示例:
const date1 = new Date('2021-05-12T00:00:00.000Z'); // ISO 8601 string
const date2 = new Date('12 May 2021 01:00:00 UTC+3');
const diffInMilliseconds = date2 - date1;
const diffInHours = diffInMilliseconds / 1000 / 60 / 60;
console.log(diffInHours); // 1 or -2?
这里的答案是 -2,因为 的时区date1
是 UTC,而 的时区date2
是 UTC+3。让我们更详细地看看发生了什么:
- 我们
date1
使用 ISO 8601 格式将其设置为 2021 年 5 月 12 日 00:00:00 UTC。我们使用字符 Z 指定 UTC 时区。我们也可以使用偏移量指定时区,例如:2021-05-12T00:00:00.000+00:00(+00:00 为 UTC)。 - 我们
date2
使用时区偏移量为 UTC+3(或 UTC+03:00)的另一个日期和时间格式将其设置为 2021 年 5 月 12 日 01:00:00。 - 然后我们从 date2 (
date2 - date1
) 中减去 date1 。当我们对对象使用数学运算时,JavaScript 会使用该对象的valueOf()方法(如果存在)将对象转换为数字。对于 Date 对象,该valueOf
方法返回自 Unix 纪元以来的毫秒数作为日期和时间,Unix 纪元是基于 UTC 的日期和时间表示。因此,date1
已设置为 UTC,而已date2
从 UTC+3 转换为 UTC。因此,实际上,我们date1
从 2021 年 5 月 11 日 22:00:00 UTC ( ) 中减去 2021 年 5 月 12 日 01:00:00 UTC (date2
),这就是我们得到结果 -2 的原因。
格式化日期
格式化日期的一种方法是使用 getter 函数,如 getFullYear、getMonth、getDate 等。例如,要以“YYYY-MM-DD hh:mm:ss”格式创建本地时间的日期和时间字符串,我们可以执行以下操作:
const date = new Date();
const year = date.getFullYear();
const month = date.getMonth(); // getMonth returns a zero-based index of the month: 0-11
const day = date.getDate(); // 0 - 31
const hours = date.getHours(); // 0 - 23
const minutes = date.getMinutes(); // 0 - 59
const seconds = date.getSeconds(); // 0 - 59
const addZero = (num) => `${num}`.padStart(2, '0');
const formatted =
year +
'-' +
addZero(month + 1) +
'-' +
addZero(day) +
' ' +
addZero(hours) +
':' +
addZero(minutes) +
':' +
addZero(seconds);
为了根据 UTC 获取日期和时间值,我们可以使用基于 UTC 的 getter 函数,如 getUTCFullYear、getUTCMonth、getUTCDate 等。
此外,我们可以使用 Date 的方法从 Date 对象中获取根据给定语言环境和各种选项格式化的日期和时间字符串toLocaleString
:
new Date('2021-05-16').toLocaleString('uk');
// 16.05.2021, 03:00:00
new Date('2021-05-16').toLocaleString('en', {
month: 'long',
});
// May
new Date('2021-05-16').toLocaleString('en', {
month: 'long',
day: 'numeric',
year: 'numeric',
});
// May 16, 2021
请注意,如果您没有在选项中指定时区,toLocaleString
则会以当地时区输出日期:
new Date('2021-05-16T00:00:00').toLocaleString('en', {
timeZoneName: 'short', // include the time zone name
});
// "5/16/2021, 12:00:00 AM GMT+3" (GMT+3 is my local time zone)
new Date('2021-05-16T00:00:00').toLocaleString('en', {
timeZoneName: 'short',
timeZone: 'Europe/Amsterdam',
});
// 5/15/2021, 11:00:00 PM GMT+2
首先,我们使用本地时区实例化 Date 对象,并获取本地化的日期和时间字符串。实例化 Date 时,日期和时间值会在内部从指定时区(如果未指定时区,则为本地时区)转换为 UTC。
然后,我们实例化另一个带有本地时区的 Date 对象。这次我们将选项设置timeZone
为“Europe/Amsterdam”(根据 IANA 时区数据库)。因此,我们获取了基于“Europe/Amsterdam”时区的本地化日期和时间字符串。更详细地说:我当前的时区是 UTC+3,因此 Date 对象实例化的日期和时间为 2021-05-16 00:00:00 UTC+3,该日期和时间在内部转换为 UTC,即 2021-05-15 21:00:00。然后,该toLocaleString
方法将此日期从 UTC 转换为“Europe/Amsterdam”,结果为 2021/5/15, 11:00:00 PM GMT+2。结果偏移量为 +2,因为这是“Europe/Amsterdam”时区的夏令时偏移量。
后端的时区
通常,计算机软件(例如 Node.js、数据库等)默认使用系统日期和时间配置。因此,请确保您应用的所有服务器都使用相同的时区。通常使用 UTC 时间。
在 Linux 中,您可以使用以下命令之一检查时区:
date
date +"%Z %z"
timedatectl
要更改系统时区,您可以使用以下命令:
# Check available time zone names
timedatectl list-timezones
# Set the time zone
timedatectl set-timezone Europe/Amsterdam
要检查 Node.js 进程的时区:
node -e "console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)"
在 Node.js 中,您可以使用环境变量设置时区TZ
:
TZ=UTC node -e "console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)"
# UTC
如果TZ
未设置该变量,Node.js 将尝试使用操作系统的时区。
在数据库中存储日期
通常,Web 应用程序可以在世界各地运行。这意味着,如果我们将日期存储在数据库中,我们需要确保所有日期都存储在一个(一致的)时区中,或者至少跟踪我们存储的日期的时区。不同的数据库对于如何处理日期和时间值都有各自的具体要求。因此,在本节中,我将简要解释如何在不同的数据库中存储日期和时间值,并提及其中的一些具体要求。
通常,软件(尤其是网络应用)服务于世界各地的用户。每个用户的本地时间取决于他们所在的位置。例如,对于来自基辅的用户来说,夏季当地时间是 17:00,而对于阿姆斯特丹的用户来说,夏季当地时间是 16:00。
基本上,我们应该将日期转换并存储在统一的时区中;通常,开发人员会使用 UTC 时间存储日期。因此,在存储日期之前,我们应该将其从本地时间转换为 UTC 时间。例如,一位来自阿姆斯特丹的用户在日历应用中创建了一个提醒。用户选择本地时间(“欧洲/阿姆斯特丹”时区 - 标准时间 UTC+01:00 和夏令时 UTC+02:00)作为提醒的日期和时间。假设用户使用日历小部件将提醒日期设置为 2021 年 5 月 12 日 17:00。现在,在将此日期存储到数据库之前,我们应该将其转换为 UTC 时间,这样日期就变成了:UTC 时间 2021 年 5 月 12 日 15:00,因为阿姆斯特丹的夏令时(UTC+02:00)已于 2021 年 3 月 28 日 02:00:00 生效。幸运的是,我们通常不需要处理时区转换逻辑,因为它通常内置于我们使用的编程语言和软件(例如数据库)中。例如,在 JavaScript 中,我们可以使用 Date 对象获取 UTC 格式的当前日期和时间:
new Date().getTime();
// number of milliseconds from Unix epoch
new Date().toISOString();
// ISO 8601 date string in UTC
MySQL
在 MySQL 中,日期通常使用DATETIME
和TIMESTAMP
列类型存储。
MySQL 时间戳
MySQL 会将TIMESTAMP
值从当前时区(例如,全局时区或客户端会话时区)转换为 UTC 以便存储,并在检索时从 UTC 转换回当前时区。MySQL 不会对其他列类型(例如)执行此操作DATETIME
。因此,TIMESTAMP
值在存储时会被转换为 UTC,但在检索时,会被转换为当前时区(SELECT @@SESSION.time_zone;
)。请参考以下示例:
CREATE TABLE timestamp_test (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
created_at TIMESTAMP NOT NULL
);
-- Set the current time zone to UTC+3
SET time_zone = '+03:00';
SELECT @@SESSION.time_zone;
-- +03:00
INSERT INTO timestamp_test (created_at) VALUES ('2021-05-12 21:00:00');
SELECT * FROM timestamp_test ORDER BY id ASC;
+----+---------------------+
| id | created_at |
+----+---------------------+
| 1 | 2021-05-12 21:00:00 |
+----+---------------------+
-- Set the current time zone to UTC+4
SET time_zone = '+04:00';
SELECT * FROM timestamp_test ORDER BY id ASC;
+----+---------------------+
| id | created_at |
+----+---------------------+
| 1 | 2021-05-12 22:00:00 |
+----+---------------------+
TIMESTAMP
从 MySQL 8.0.19 开始,我们可以在将DATETIME
值插入表中时添加时区偏移量:
-- 1.
SET time_zone = '+02:00';
-- 2.
INSERT INTO timestamp_test (created_at) VALUES ('2021-05-12 21:00:00-01:00');
-- 3.
SELECT * FROM timestamp_test ORDER BY id ASC;
+----+---------------------+
| id | created_at |
+----+---------------------+
| 1 | 2021-05-12 20:00:00 |
| 2 | 2021-05-13 00:00:00 |
+----+---------------------+
-- 4.
SET time_zone = '+03:00';
SELECT * FROM timestamp_test ORDER BY id ASC;
+----+---------------------+
| id | created_at |
+----+---------------------+
| 1 | 2021-05-12 21:00:00 |
| 2 | 2021-05-13 01:00:00 |
+----+---------------------+
让我们看看这个例子中发生了什么:
- 我们将当前时区设置为 UTC+2
- 我们插入一个时区偏移为 UTC-1 的日期值:2021-05-12 21:00:00-01:00。MySQL 会将此日期和时间值从 UTC-1 转换为 UTC 进行存储:2021-05-12 22:00:00。
- 我们从表中选择行,MySQL
TIMESTAMP
在检索时将值从 UTC 转换为当前时区 (UTC+2):2021-05-13 00:00:00 - 然后,我们将时区设置为 UTC+3 并再次选择行,并且由于 MySQL
TIMESTAMP
在检索时将值从 UTC 转换为当前时区,因此我们这次获得了 UTC+3 中先前插入的日期:2021-05-13 01:00:00
该TIMESTAMP
类型的范围为 1970-01-01 00:00:01 UTC 至 2038-01-19 03:14:07 UTC。
MySQL 日期时间
MySQLDATETIME
按原样存储和检索:
CREATE TABLE datetime_test (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
created_at DATETIME NOT NULL
);
-- Set the current time zone to UTC+3
SET time_zone = '+03:00';
INSERT INTO datetime_test (created_at) VALUES ('2021-05-12 21:00:00');
SELECT * FROM datetime_test ORDER BY id ASC;
+----+---------------------+
| id | created_at |
+----+---------------------+
| 1 | 2021-05-12 21:00:00 |
+----+---------------------+
-- Set the current time zone to UTC+4
SET time_zone = '+04:00';
SELECT * FROM datetime_test ORDER BY id ASC;
+----+---------------------+
| id | created_at |
+----+---------------------+
| 1 | 2021-05-12 21:00:00 |
+----+---------------------+
MySQL 不会将DATETIME
当前时区的值转换为 UTC,反之亦然。
然而,当我们插入DATETIME
一个带有时区偏移的值时,会发生一些有趣的事情:
-- Set the current time zone to UTC+3
SET time_zone = '+03:00';
-- Insert a date with the time zone offset UTC+0
INSERT INTO datetime_test (created_at) VALUES ('2021-05-12 21:00:00+00:00');
SELECT * FROM datetime_test ORDER BY id ASC;
+----+---------------------+
| id | created_at |
+----+---------------------+
| ... |
| 2 | 2021-05-13 00:00:00 |
+----+---------------------+
在上面的例子中我们可以看到,当我们插入DATETIME
一个带有时区偏移的值时,MySQL 会将此日期值转换为当前时区进行存储:2021-05-12 21:00:00+00:00 + 当前时区偏移量(+03:00)= 2021-05-13 00:00:00
该DATETIME
类型的范围为 1000-01-01 00:00:00 至 9999-12-31 23:59:59。
要存储日期和时间值,我会在应用程序代码中将本地日期和时间值转换为 UTC,并将该值存储在 DATETIME 列中。基本上,我会在应用程序端处理时区转换,并将所有日期存储为 UTC 格式。我会使用 DATETIME 而不是 TIMESTAMP,因为 TIMESTAMP 实际上是 32 位整数,不允许存储超过 2038-01-19 03:14:07 UTC 的日期,而 DATETIME 允许存储最晚到 9999-12-31 23:59:59.999999 的日期。
PostgreSQL
在 PostgreSQL 中,我们通常使用列类型timestamp without time zone
(或简称timestamp
)或timestamp with time zone
(或简称timestamptz
)来存储日期和时间值。这两种类型的范围都是公元前 4713 年至公元 294276 年。
PostgreSQL 时间戳(无时区)
这些timestamp without time zone
值按原样存储和检索:
CREATE TABLE without_time_zone(
id SERIAL PRIMARY KEY,
created_at TIMESTAMP NOT NULL
);
INSERT INTO without_time_zone (created_at) VALUES ('2021-05-12 09:00:00');
SELECT * FROM without_time_zone ORDER BY id ASC;
-- 1 "2021-05-12 09:00:00"
INSERT INTO without_time_zone (created_at) VALUES ('2021-05-12 09:00:00 +01:00');
SELECT * FROM without_time_zone ORDER BY id ASC;
-- 1 "2021-05-12 09:00:00"
-- 2 "2021-05-12 09:00:00"
在此示例中,我们创建了一个timestamp without time zone
名为 created_at 的列。我们可以清楚地看到,日期和时间值按原样存储和检索到此列中。如果我们指定时区,则时区将被忽略。
带时区的 PostgreSQL 时间戳
timestamp with time zone
( )值timestamptz
将从指定时区转换为 UTC。如果插入值时未指定时区timestamptz
,PostgreSQL 将假定此日期值基于当前时区 ( SHOW time zone;
)。
-- 1.
CREATE TABLE with_time_zone(
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE NOT NULL
);
-- 2.
-- Set current time zone for the session to UTC+3
SET time zone 3;
-- 3.
SHOW time zone;
-- <+03>-03
-- 4.
INSERT INTO with_time_zone (created_at) VALUES ('2021-05-12 09:00:00 +01:00');
-- 5.
SELECT * FROM with_time_zone ORDER BY id ASC;
-- 1 "2021-05-12 11:00:00+03"
-- 6.
INSERT INTO with_time_zone (created_at) VALUES ('2021-05-12 09:00:00');
-- 7.
SELECT * FROM with_time_zone ORDER BY id ASC;
-- 1 "2021-05-12 11:00:00+03"
-- 2 "2021-05-12 09:00:00+03"
本例中发生的情况如下:
- 我们创建一个表,其中有一列名为 created_at,其类型为
timestamp with time zone
。 - 我们将会话的当前时区设置为 UTC+3。请注意,在 PostgreSQL 中,我们可以使用整数偏移量或时区名称(例如 America/New_York)来指定当前时区。要获取受支持的时区名称列表,请查询 pg_timezone_names 表:
SELECT * FROM pg_timezone_names
- 我们确保时区偏移已正确设置。
- 我们在新表中插入一行,其 created_at 值为 2021-05-12 09:00:00 +01:00。由于 created_at 列的类型为
timestamp with time zone
,PostgreSQL 会将指定时区(本例中为 +01:00)的日期值转换为 UTC 时间进行存储。因此,实际存储的值为“2021-05-12 08:00:00”。 - 我们从表中选择插入的行,并将日期值从 UTC 转换为当前时区偏移量,即 UTC+3。
- 我们在表中插入另一行,但这次不指定时区偏移量。如果不包含时区偏移量,PostgreSQL 会假定我们提供的日期值基于当前时区,在本例中为 UTC+3。因此,在存储此日期值之前,PostgreSQL 会将其从当前时区(在本例中为 UTC+3)转换为 UTC,并将存储以下日期值:2021-05-12 06:00:00 UTC
- 最后,我们再次从表中选择所有行,并看到刚刚插入的日期值显示在当前时区:2021-05-12 09:00:00+03
要在 PostgreSQL 中存储日期和时间值,我会使用timestamp with time zone (timestamptz)
类型。基本上,我会选择 timestamptz 而不是 timestamp,原因在 PostgreSQL Wiki 的以下文章中提到:不要这样做 - 日期/时间存储。
DynamoDB
您可以使用字符串和数字数据类型来存储日期和时间戳。我们可以使用字符串数据类型以 ISO 8601 格式存储日期和时间值(例如,2021-05-12,2021-05-12T21:00:59.123Z)。我们可以使用数字数据类型将日期和时间值存储为 UNIX 时间戳(纪元时间)——自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数。这将使我们能够按日期和时间对项目进行排序和查询。
MongoDB
在 MongoDB 内部,日期存储为 64 位有符号整数,表示自 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)以来的毫秒数。负值表示 Unix 纪元之前的日期。
要在 Mongo shell 中插入日期,我们可以使用 Date 对象:
// Specifying the current date and time value when inserting an item:
db.books.insertOne({ title: 'Book 1', createdAt: new Date() })
db.books.find()
/*
{
"_id" : ObjectId("60a5481cdff09849800652de"),
"title" : "Book 1",
"createdAt" : ISODate("2021-05-19T17:17:16.634Z")
}
您可以将 ISO 8601 字符串或自 Unix 纪元以来的毫秒数传递到 Date 构造函数中:
new Date('2021-05-19');
new Date('2021-05-19T00:00:00Z');
new Date(1621382400000);
如果指定时区偏移量,日期将转换为 UTC:
new Date('2021-05-19T00:00:00+02:00');
// becomes 2021-05-18T22:00:00Z
结论
处理日期和时间时务必谨慎。务必检查存储和使用的日期是否基于您预期的时区。确保用于运行应用不同部分(例如,Web 服务器、数据库等)的环境具有正确且一致的时区配置。
有用的资源
- 时区 - 维基百科
- 日期 - MDN Web 文档
- DATE、DATETIME 和 TIMESTAMP 类型 - MySQL 手册
- MySQL 服务器时区支持 - MySQL 手册
- 日期/时间类型 - PostgreSQL 文档
- 不要这样做 - 日期/时间存储
- 数据类型 - Amazon DynamoDB 开发人员指南
- mongo Shell 中的数据类型 - MongoDB 手册
- BSON 类型 - 日期 - MongoDB 手册
- UTC 时间偏移列表
- 各国夏令时
- tz 数据库 - 维基百科