返回

用时隔两年的实践经验,助你避开时间转换坑

后端

前言

作为一名软件工程师,我经常需要处理时间转换的任务。时间转换看似简单,但实际上却有很多坑。在过去的两年里,我踩过不少坑,也总结了一些解决方法。本文将分享我的经验,帮助大家避开时间转换的坑。

正确示例

// JavaScript
const date = new Date('2023-03-08T12:34:56Z');
console.log(date.toLocaleDateString()); // "3/8/2023"
console.log(date.toLocaleTimeString()); // "12:34:56 PM"
# Python
import datetime

date = datetime.datetime(2023, 3, 8, 12, 34, 56)
print(date.strftime('%Y-%m-%d')) # "2023-03-08"
print(date.strftime('%H:%M:%S')) # "12:34:56"
// Java
import java.util.Date;
import java.text.SimpleDateFormat;

Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(date)); // "2023-03-08 12:34:56"
# C++
#include <iostream>
#include <ctime>

int main() {
  time_t t = time(0);
  tm* now = localtime(&t);
  std::cout << now->tm_year + 1900 << '-' << now->tm_mon + 1 << '-' << now->tm_mday << ' ' << now->tm_hour << ':' << now->tm_min << ':' << now->tm_sec << std::endl;
  return 0;
}
// PHP
<?php
$date = new DateTime('2023-03-08 12:34:56');
echo $date->format('Y-m-d'); // "2023-03-08"
echo $date->format('H:i:s'); // "12:34:56"
?>

错误实例

// JavaScript
const date = new Date('2023-03-08');
console.log(date.toLocaleDateString()); // "3/7/2023"
console.log(date.toLocaleTimeString()); // "12:00:00 AM"

在这个示例中,我们使用 new Date('2023-03-08') 创建了一个日期对象。但是,这个日期对象的时区是本地时区,而不是 UTC 时区。因此,当我们使用 toLocaleDateString()toLocaleTimeString() 方法时,日期和时间都被转换成了本地时区。

# Python
import datetime

date = datetime.datetime(2023, 3, 8)
print(date.strftime('%Y-%m-%d')) # "2023-03-07"
print(date.strftime('%H:%M:%S')) # "00:00:00"

在这个示例中,我们使用 datetime.datetime(2023, 3, 8) 创建了一个日期对象。但是,这个日期对象没有指定时区。因此,当我们使用 strftime() 方法时,日期和时间都被转换成了本地时区。

// Java
import java.util.Date;
import java.text.SimpleDateFormat;

Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(sdf.format(date)); // "2023-03-07"

在这个示例中,我们使用 new Date() 创建了一个日期对象。但是,这个日期对象没有指定时区。因此,当我们使用 SimpleDateFormat 类格式化日期时,日期被转换成了本地时区。

# C++
#include <iostream>
#include <ctime>

int main() {
  time_t t = time(0);
  tm* now = localtime(&t);
  std::cout << now->tm_year + 1900 << '-' << now->tm_mon << '-' << now->tm_mday << std::endl;
  return 0;
}

在这个示例中,我们使用 time(0) 获取当前时间戳。然后,我们使用 localtime() 函数将时间戳转换为本地时区的 tm 结构体。最后,我们使用 tm 结构体中的字段格式化日期。

// PHP
<?php
$date = new DateTime();
echo $date->format('Y-m-d'); // "2023-03-07"
?>

在这个示例中,我们使用 new DateTime() 创建了一个日期对象。但是,这个日期对象没有指定时区。因此,当我们使用 format() 方法格式化日期时,日期被转换成了本地时区。

解决方法

要避免这些坑,我们需要使用正确的时区。在 JavaScript 中,我们可以使用 Date.UTC() 方法创建一个指定时区的日期对象。在 Python 中,我们可以使用 datetime.datetime() 方法并指定时区。在 Java 中,我们可以使用 SimpleDateFormat 类并指定时区。在 C++ 中,我们可以使用 mktime() 函数创建一个指定时区的日期对象。在 PHP 中,我们可以使用 DateTime 类并指定时区。

以下是使用正确时区的示例:

// JavaScript
const date = new Date(Date.UTC(2023, 2, 8, 12, 34, 56));
console.log(date.toLocaleDateString()); // "3/8/2023"
console.log(date.toLocaleTimeString()); // "12:34:56 PM"
# Python
import datetime

date = datetime.datetime(2023, 3, 8, 12, 34, 56, tzinfo=datetime.timezone.utc)
print(date.strftime('%Y-%m-%d')) # "2023-03-08"
print(date.strftime('%H:%M:%S')) # "12:34:56"
// Java
import java.util.Date;
import java.text.SimpleDateFormat;

Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(sdf.format(date)); // "2023-03-08 12:34:56"
# C++
#include <iostream>
#include <ctime>

int main() {
  time_t t = time(0);
  tm* now = gmtime(&t);
  std::cout << now->tm_year + 1900 << '-' << now->tm_mon + 1 << '-' << now->tm_mday << ' ' << now->tm_hour << ':' << now->tm_min << ':' << now->tm_sec << std::endl;
  return 0;
}
// PHP
<?php
$date = new DateTime('2023-03-08 12:34:56', new DateTimeZone('UTC'));
echo $date->format('Y-m-d'); // "2023-03-08"
echo $date->format('H:i:s'); // "12:34:56"
?>

总结

时间转换是一个常见的任务,但它也充满了坑。在本文中,我分享了一些常见的坑以及解决方法。希望这些内容对大家有所帮助。

最后,我想说的是,时间转换只是一个工具。重要的是要理解你为什么要转换时间,以及你想要转换什么。只有这样,你才能正确地使用时间转换工具。