时间 软件开发
2023-04-10
https://en.wikipedia.org/wiki/ISO_8601
占位符
占位符 |
描述 |
%Y |
四位数的年份 |
%m |
两位数的月份 |
%d |
两位数的日数 |
%H |
24 小时制的小时数 |
%M |
两位数的分钟数 |
%S |
两位数的秒数 |
%z |
时区偏移量,格式如 +0800 |
%a |
星期几的缩写,例如:Mon、Tue 等 |
%A |
星期几的全称,例如:Monday、Tuesday 等 |
%b |
月份的缩写,例如:Jan、Feb 等 |
%B |
月份的全称,例如:January、February 等 |
%c |
本地日期时间,例如:Tue Aug 16 21:30:00 1988 |
%f |
微秒,范围是 0~999999 |
%j |
年份中的第几天,范围是 001~366 |
%p |
上午或下午,例如:AM、PM |
%r |
12 小时制的时间,例如:09:30:00 PM |
%s |
自 1970 年 1 月 1 日以来的秒数 |
%u |
星期几,范围是 1~7,其中 1 表示星期一 |
%w |
星期几,范围是 0~6,其中 0 表示星期日 |
%x |
本地日期,例如:08/16/88 |
%X |
本地时间,例如:21:30:00 |
%y |
两位数的年份,例如:88 |
%Z |
时区名称或缩写,例如:UTC、GMT、EST 等 |
Linux
date -u +"%Y-%m-%dT%H:%M:%S.%3NZ"
Python
import datetime
now = datetime.datetime.now()
iso8601 = now.isoformat(timespec='milliseconds')
print(iso8601)
PHP
$now = new DateTime();
$iso8601 = $now->format('Y-m-d\TH:i:s.v\Z');
echo $iso8601;
Java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
String iso8601 = now.format(formatter);
System.out.println(iso8601);
JS
const now = new Date();
const iso8601 = now.toISOString();
console.log(iso8601);
C
#include <stdio.h>
#include <time.h>
int main() {
char iso8601[30];
time_t now = time(NULL);
strftime(iso8601, sizeof iso8601, "%Y-%m-%dT%H:%M:%S.000Z", gmtime(&now));
printf("%s\n", iso8601);
return 0;
}
Golang
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now().UTC()
iso8601 := now.Format("2006-01-02T15:04:05.000Z")
fmt.Println(iso8601)
}
Python 时间 Cygwin
2023-02-24
Cygwin 下执行一个 Python 脚本,其中 datetime.now()
获取到的时间居然是 UTF 时间。
执行 date 命令也是如此。
执行 tzselect,三次分别选 Asia,China,Beijing Time,然后就好了。
命令中有提示:如果要永久有效,需要在 ~/.profile 中加入 TZ='Asia/Shanghai'
。
关键是,TZ 其实有配置:
export | grep TZ
declare -x TZ="Asia/Shanghai"
Email 时间
2018-04-10
比如:
Sun, 20 Jun 2018 00:47:04 -0700 (PDT)
Thu, 10 Jun 2021 16:10:03 -0700 (PDT)
Thu, 10 Jun 2021 08:06:31 -0700 (PDT)
定义
定义在 RFC 822 的 5. DATE AND TIME SPECIFICATION。
date-time = [ day "," ] date time ; dd mm yy hh:mm:ss zzz
day = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"
date = 1*2DIGIT month 2DIGIT ; day month year e.g. 20 Jun 82
month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
time = hour zone ; ANSI and Military
hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
; 00:00:00 - 23:59:59
zone = "UT" / "GMT" ; Universal Time
; North American : UT
/ "EST" / "EDT" ; Eastern: - 5/ - 4
/ "CST" / "CDT" ; Central: - 6/ - 5
/ "MST" / "MDT" ; Mountain: - 7/ - 6
/ "PST" / "PDT" ; Pacific: - 8/ - 7
/ 1ALPHA ; Military: Z = UT;
; A:-1; (J not used)
; M:-12; N:+1; Y:+12
/ ( ("+" / "-") 4DIGIT ) ; Local differential
; hours+min. (HHMM)
总结就是:
[day-of-week,] day month year hour:minute[:second] timezone
- 周几和秒是可选的,据我观察,没有邮件省略这两部分
- 周几和月份采用三字母英文缩写(首字母大写)
- 年份是 2 位数字,后来的规范更新中建议采用 4 位数字。出于兼容性考虑,一般都保留了对 RFC 822 两位数字年份的支持。
- 时区除了数字之外,可以使用
UT
、GMT
、EST
、EDT
、CST
、CDT
、MST
、MDT
、PST
、PDT
,
还有 25 个字母(J 没有使用),Z 表示 UTC/GMT 时间,A - M 表示 -1 ~ -12 时区,N - Y 表示 1 到 12 时区。
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
West |
A |
B |
C |
D |
E |
F |
G |
H |
I |
K |
L |
M |
Eest |
N |
O |
P |
Q |
R |
S |
T |
U |
V |
W |
X |
Y |
Python
生成符合要求的时间字符串比较简单:
import time
time.strftime('%a, %d %b %Y %H:%M:%S %z')
# 'Tue, 10 Apr 2018 09:10:05 +0800'
但是由于这个灵活度比较大,解析起来最好借助专业的库(email.utils
)来做这个事。
import time
import datetime
import email.utils
import pytz
# 解析 ############################################
date_str = 'Sun, 20 Jun 2018 00:47:04 -0700 (PDT)'
email.utils.parsedate_to_datetime(date_str)
# datetime.datetime(2018, 6, 20, 0, 47, 4, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
email.utils.parsedate_tz(date_str)
(2018, 6, 20, 0, 47, 4, 0, 1, -1, -25200)
# 生成 ############################################
# email.utils.formatdate(timeval=None, localtime=False, usegmt=False)
email.utils.formatdate()
# 'Tue, 10 Apr 2018 09:10:41 -0000'
# email.utils.format_datetime(dt, usegmt=False)
dt = datetime.datetime.now()
email.utils.format_datetime(dt)
# 'Tue, 10 Apr 2018 09:16:43 -0000'
tz = pytz.timezone('Asia/Shanghai') # <DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>
dt = datetime.datetime(2018, 4, 10, 9, 10, 0, tzinfo=tz)
# datetime.datetime(2018, 4, 10, 9, 10, tzinfo=<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>)
email.utils.format_datetime(dt)
# 'Tue, 10 Apr 2018 09:10:00 +0806'