每次需要格式化时间和日期时都要在网上查询相关的教程,索性自己写一份总结用来备忘好了。

每种语言中对日期的描述不一定一样,但是日期时间的表达方式无非几种:时间戳(给机器看)、字符串(给人看)以及日期时间对象(计算、运行时)。

按照如下几种常用的操作进行整理:获取当前时间(日期),字符串转时间(日期)对象,时间(日期)对象转字符串,时间戳转时间(日期)对象,时间(日期)对象转时间戳。

首先,明确一些基本概念:

  • 时间戳 是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。 现在一般为10位数字。也见过13位时间戳,表示的是精确到毫秒。
  • UTC 协调世界时。按照原子钟计算的世界时间UT并不完全就是我们生活的时间。经过平均太阳时、地轴运动修正的新时标和国际原子时综合精算,得到UTC。
  • 时区。时间的表示和时区有关,一个时间戳要在知道时区的情况下才能正确转换成时分秒所表示的时间。如果不规定时区,则一般默认采用UTC+0,刚好和GMT(格林威治时间)相同。
  • 在时间的表示中,T表示日期和时间的分隔,而末尾的Z表示这是UTC标准时间。如果末尾不是Z而是+16:00类似的表示,则说明是对应的时区,+16:00表示此处比UTC快16小时。

Python

用到的库:datetime(原生,无需额外安装)

datetime库中有好几个类,经常使用:

  • date 日期
  • time 时间
  • datetime 日期+时间
  • timedelta 时间偏移量

date

使用时首先要from datetime import date

获取当前日期

from datetime import date

today = date.today()
print(today)
# output(example):
# 2022-09-24

字符串转日期

from datetime import date
date_from_str = date.fromisoformat("2022-09-24")
print(date_from_str)
# output
# 2022-09-24

日期转字符串

from datetime import date
str_from_date = date.today().strftime(format='%Y-%m-%d %a %H%M%S')
print(str_from_date)
# output(example)
# 2022-09-24 Sat 000000

时间戳转日期

from datetime import date,datetime
now_day = date.fromtimestamp(datetime.now().timestamp())
print(now_day)
# output(example)
# 2022-09-24

datetime

获取当前时间

from datetime import datetime
print(datetime.now())
# output(example)
# 2022-09-24 13:25:21.517404
# 默认UTC+0

字符串转时间

from datetime import datetime
print(datetime.fromisoformat("2011-11-04T00:05:23+04:00"))
# output
# 2011-11-04 00:05:23+04:00
# python不支持末尾有Z的,直接去掉Z转换就可以了

或者另一种更加通用的strptime函数:

from datetime import datetime
print(datetime.strptime(r"2011-11-04T00:05:23.283+04:00", r"%Y-%m-%dT%H:%M:%S.%f%z"))
print(datetime.strptime(r"2011-11-04T00:05:23.283000+0400", r"%Y-%m-%dT%H:%M:%S.%f%z"))
# output:
# 2011-11-04 00:05:23.283000+04:00
# 2011-11-04 00:05:23.283000+04:00

时间转字符串

from datetime import datetime
test_time = datetime.strptime(r"2011-11-04T00:05:23.283+04:00", r"%Y-%m-%dT%H:%M:%S.%f%z")
print(test_time.strftime("%y-%m-%dT%H%p%M:%S%Z"))
# output
# 11-11-04T00AM05:23UTC+04:00

时间戳转时间

from datetime import datetime
test_time = datetime.fromtimestamp(1664027067)
print(test_time)
# output
# 2022-09-24 13:44:27
# 只接受10位时间戳

时间转时间戳

from datetime import datetime
test_time = datetime.fromtimestamp(1664027067)
print(test_time.timestamp())
# output
# 1664027067.0
# Python中时间戳是float类型的

timedelta

表示时间段、时间偏移量,可以直接和date、datetime对象相加,例如

from datetime import datetime, timedelta
new_time = datetime.now() + timedelta(days = 1)
print(new_time)
# output
# 2022-09-25 13:48:16.031319

Java

Java中使用Date类来表示日期和时间。jdk8以后,引入了新的LocalDateTime类表示时间,更加灵活。

Date

获取当前时间

Date date = new Date();

时间转字符串

Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss zzzz", Locale.JAPAN);
// 设定时区
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
System.out.println(simpleDateFormat.format(date));

字符串转时间

String timeStr = "2022-09-25 02:21:38 CST";
try {
    Date dateParsed = simpleDateFormat.parse(timeStr);
    System.out.println(simpleDateFormat.format(dateParsed));
} catch (ParseException e) {
    throw new RuntimeException(e);
}

时间转时间戳

// Java 默认13位时间戳,带毫秒
System.out.println(date.getTime());

时间戳转时间

Date date1 = new Date(1664044092703L);

时间跨度的计算

时间跨度最佳计算方法是用时间戳进行计算。借助TimeUnit库来转换各个单位到毫秒后,就可以在时间戳上直接加减处理。

long millis = TimeUnit.DAYS.toMillis(1);
Date date2 = new Date(date1.getTime() + millis);
System.out.println(date2);

LocalDateTime

此部分参考ZonedDateTime - 廖雪峰的官方网站 (liaoxuefeng.com)

LocalDateTime系列有三个组件:LocalDate、LocalTime、LocalDateTime,ZonedDateTime和Instant

关系如下:

image-20221115174836192

即,LocalDateTime通过标注时区可以得到ZonedDateTime,然后ZonedDateTime可以转为Instant和时间戳。

获得当前时间

LocalDate d = LocalDate.now(); // 当前日期
LocalTime t = LocalTime.now(); // 当前时间
LocalDateTime dt = LocalDateTime.now(); // 当前日期和时间
System.out.println(d); // 严格按照ISO 8601格式打印
System.out.println(t); // 严格按照ISO 8601格式打印
System.out.println(dt); // 严格按照ISO 8601格式打印

// 获得时间戳
Instant instant = Instant.now();
long timeStampMillis = instant.toEpochMilli(); // 获得13位时间戳
long timeStampSeconds = instant.getEpochSecond(); // 获得10位时间戳

类型互转

// 以上方法可能会以为执行语句的时间消耗导致前后d t dt产生的时间不一致,可以用下面的方式获得一致的date和time
LocalDateTime dt2 = LocalDateTime.now(); // 当前日期和时间
LocalDate d2 = dt2.toLocalDate(); // 转换到当前日期
LocalTime t2 = dt2.toLocalTime(); // 转换到当前时间
LocalDateTime localDateTime = localDate.atStartOfDay(); // 日期转时间日期
LocalDateTime localDateTime2 = localTime.atDate(d2); // 时间转时间日期

时间加减和调整

可以给时间做简单的加减和设置。

LocalDateTime dt2 = dt.plusDays(5).minusHours(3);
LocalDateTime dt3 = dt.withDayOfMonth(31);

时间转字符串

String dateString = LocalDate.now().toString();
String timeString = LocalTime.now().toString();
String dateTimeString = LocalDateTime.now().toString();

字符串转时间

通过parse方法

LocalDate localDate = LocalDate.parse("2022-11-15");
LocalTime localTime = LocalTime.parse("16:59:38.332");
LocalDateTime localDateTime = LocalDateTime.parse("2022-11-15T16:59:38.332");

时间转时间戳

因为LocalDateTime没有时区信息,因此不能直接转时间戳,要先标注时区变成ZonedDateTime再转,再转成高精度时间戳类Instant

LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime ctt = localDateTime.atZone(ZoneId.of("CTT")); //处理时区
long timestamp = ctt.toInstant().toEpochMilli(); // 13位时间戳
long epochSecond = ctt.toInstant().getEpochSecond(); // 10位时间戳

时间戳转时间

Instant ins = Instant.ofEpochSecond(1568568760L);
ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault());

JavaScript

JavaScript 中使用 Date类表示时间。

获取当前时间

// 获得的是一个13位时间戳
let timestamp = new Date().getTime();

其他语言的还在施工中,日后补充……