#213 常见的时间格式

2017-07-24

日常使用

中国人习惯年月日时分秒,这可能也是一般符合国际通行规范的时间格式。

yymmdd
yyyymmdd
yyyy-mm-dd hh:mm:ss
yyyy/mm/dd hh:mm:ss

如果加上毫秒/微秒,在秒后面接上 ,SSS.SSS 就行。

但是由于英美的国际地位,以及由于历史原因而导致的英语的强势地位,英文国家的表述习惯也不能不考虑,

  • May 4, 1919 美式英语,读 may forth nineteen nineteen
  • 4 May, 1919 英式英语

用阿拉伯数字表示的话,可以用小数点、横杠、斜杠连接,数字可以用前导 0,
不过有一点很悲剧了,5/4/1919,如果不清楚上下文语境中的文化背景,谁 TM 知道应该算五四,还是四五。

Unix 时间戳

Unix Timestamp

又叫 Unix 时间(Unix Time),又叫 POSIX 时间(POSIX Time),又叫 Epoch Time。

以 UTC+0:00 1970/01/01 00:00:00 为起点,至今的秒数就是时间戳的值。

实际上我在很多项目中用到的时间戳都没有考虑时区,直接用当前系统默认时区的 1970/01/01 00:00:00 为起点,或者说是把当前时区时间当作零时区时间。

RFC2822

Internet Message Format, 邮件格式

date-time       =       [ day-of-week "," ] date FWS time [CFWS]
day-of-week     =       ([FWS] day-name) / obs-day-of-week
day-name        =       "Mon" / "Tue" / "Wed" / "Thu" /
                        "Fri" / "Sat" / "Sun"
date            =       day month year
year            =       4*DIGIT / obs-year
month           =       (FWS month-name FWS) / obs-month
month-name      =       "Jan" / "Feb" / "Mar" / "Apr" /
                        "May" / "Jun" / "Jul" / "Aug" /
                        "Sep" / "Oct" / "Nov" / "Dec"
day             =       ([FWS] 1*2DIGIT) / obs-day
time            =       time-of-day FWS zone
time-of-day     =       hour ":" minute [ ":" second ]
hour            =       2DIGIT / obs-hour
minute          =       2DIGIT / obs-minute
second          =       2DIGIT / obs-second
zone            =       (( "+" / "-" ) 4DIGIT) / obs-zone

1992/02/12 12:23:22+0800

Wed, 21 Jul 2017 10:35:00 +0000 (UTC)
Wed, 21 Jul 2017 18:35:19 +0800 (CST)
Wed, 21 Jul 2017 03:35:02 -0700 (PDT)
import time
import datetime

time.strftime('%a, %d %b %Y %H:%M:%S %z')  # local timezone
time.strftime('%a, %d %b %Y %H:%M:%S %z', time.gmtime())  # UTC

tz_e8 = datetime.timezone(datetime.timedelta(hours=8)) # +08:00
dt_e8 = datetime.datetime.now(tz_e8)
print(dt_e8)
print(dt_e8.strftime('%a, %d %b %Y %H:%M:%S %z'))

tz_w8 = datetime.timezone(datetime.timedelta(hours=-8)) # -08:00
dt_w8 = datetime.datetime.now(tz_w8)
print(dt_w8.strftime('%a, %d %b %Y %H:%M:%S %z'))

# dt_e8.strftime('%Y-%m-%d %H:%M:%S.%f')

ISO8601

约定了时间中各个部分的格式,比如年份应该采用四位数字,日期应该怎么表示,时间范围(比如一个月),循环时间,时间区间应该如何表示之类,是一份完整的时间相关规范。

对应的中国国家标准是 GB/T 7408-2005

比如我们要说的完整时间格式化就有几种允许的格式,下面就是常见的一种符合规范的表述:

YYYY-MM-DDThh:mm:ss+offset

例如:

2004-05-03T17:30:08Z
2004-05-03T17:30:08+08:00

其他

JavaScript 日期输出:

Sat Jul 24 2017 15:42:49 GMT+0800 (中国标准时间)

Python datatime 类型转字符串:

2017-07-25 12:09:39.123173+08:00

#210 域名查询 dig

2017-06-02

dig(Domain Information Groper)是 DNS 查询与诊断工具,功能比 nslookup 更强大,是 Linux 运维、网络工程和 DNS 管理中最常用的调试工具。它能够查询各种 DNS 记录、追踪完整解析过程、指定 DNS 服务器、查看权威应答和调试 DNSSEC 信息,是分析域名解析问题的标准工具。

命令 作用
dig qq.com 查询域名 A 记录
dig AAAA qq.com 查询 IPv6 地址记录
dig MX qq.com 查询邮件服务器记录
dig NS qq.com 查询名称服务器记录
dig TXT qq.com 查询 TXT 记录(SPF、DKIM 等)
dig CNAME qq.com 查询 CNAME 记录
dig -x 8.8.8.8 IP 反向解析(PTR 查询)
dig qq.com @8.8.8.8 使用指定 DNS 服务器查询
dig +short qq.com 仅输出结果,便于脚本处理
dig +trace qq.com 从根服务器开始追踪完整解析链路
dig ANY qq.com 查询所有可返回的记录(很多 DNS 已限制)
dig +noall +answer qq.com 仅显示 Answer 区域
dig +dnssec qq.com 查询 DNSSEC 相关信息
dig SOA qq.com 查询 SOA(区域授权)记录

dig -h 输出太多参数了,我就不贴出来了。

#209 纸张尺寸标准

2017-05-18

国际标准纸张尺寸

ISO 216(1975 年)定义了 A 系列和 B 系列纸张。
ISO 269(1985 年)定义了主要使用于信封的 C 系列纸张。
ISO 217(1985 年)定义了 RA 系列和 SRA 系列的未完成纸张。

利希滕贝格(Lichtenberg,1742-1799)是 18 世纪下半叶德国的启蒙学者,杰出的思想家、讽刺作家、政论家、物理学家。
1786 年,利希滕贝格在书信中提出纸张长宽比为 √2 可实现完美缩放,该理论成为现代 ISO 216 标准(如 A4 纸)的核心依据。

这个标准最主要的障碍是美国和加拿大,它们仍然使用 Letter(尺寸接近于 A4)、Legal(尺寸接近于 A3)、Executive 纸张尺寸系统。而加拿大用的则是一种 P 系列纸张尺寸,不过它其实是美国用的纸张尺寸,然后取最接近的公制尺寸。

基本规则:

  1. 宽高比为 $\sqrt{2}$
  2. 精度为毫米(舍弃小数部分)

不同系列:

  1. A 系列:以面积为 1 平方米的纸张为 A0,每次于长边对切,分别得到 A1,A2...
  2. B 系列:宽边为 1 米的纸张编号 B0,,每次于长边对切,分别得到 B1,B2...
  3. C 系列:A 系列和 B 系列的几何平均,比如 C0 的尺寸是 $(\sqrt{W_{A0} \times W_{B0}}, \sqrt{H_{A0} \times H_{B0}})$
    1. 这样的话,C 系列尺寸介于 A,B 之间,A 系列纸张可以放入 C 系列同一编号的信封、文件袋中。

计算下来:

| Size |      A      |      B      |      C      |
|------|-------------|-------------|-------------|
|    0 |  841 × 1189 | 1000 × 1414 |  917 × 1297 |
|    1 |  594 ×  841 |  707 × 1000 |  648 ×  917 |
|    2 |  420 ×  594 |  500 ×  707 |  458 ×  648 |
|    3 |  297 ×  420 |  353 ×  500 |  324 ×  458 |
|    4 |  210 ×  297 |  250 ×  353 |  229 ×  324 |
|    5 |  148 ×  210 |  176 ×  250 |  162 ×  229 |
|    6 |  105 ×  148 |  125 ×  176 |  114 ×  162 |
|    7 |   74 ×  105 |   88 ×  125 |   81 ×  114 |
|    8 |   52 ×   74 |   62 ×   88 |   57 ×   81 |
|    9 |   37 ×   52 |   44 ×   62 |   40 ×   57 |
|   10 |   26 ×   37 |   31 ×   44 |   28 ×   40 |

国标

国标(GB/T 148-1997)中没有定义 C 系列,但是有一个 D 系列,其尺寸定义的依据不明。
但我们经常在本子上看到的 16 开,32 开这样的字眼就从这里来的。

  1. 国标规定 D 系列原纸尺寸为 787mm x 1092mm = $859404 mm^2 \approx 0.86 m^2$
  2. $(W_{D1}, H_{D1}) = (\frac{H_{D0}}{2}, W_{D0} - 4)$
Series Size 称呼
D0 764 X 1064 全开
D1 532 X 760 半开
D2 380 X 528 4 开
D3 264 X 376 8 开
D4 188 X 260 16 开
D5 130 X 184 32 开
D6 92 X 126 64 开

A4 有些时候也被称之为大 16 开
A4 有些时候也被称之为大 32 开

北美标准(ANSI)

打印的时候经常可以看到。

#208 Linux 命名空间

2017-05-11

命名空间是什么

对内核资源进行分区,为进程隔离提供支持。

命名空间类型

Namespace CloneFlag Version Year
Mount (mnt) CLONE_NEWNS 2.4.19 2002
UTS CLONE_NEWUTS 2.6.19 2006
Inter-process Communication (ipc) CLONE_NEWIPC 2.6.19 2006
Process ID (pid) CLONE_NEWPID 2.6.24 2008
Network (net) CLONE_NEWNET 2.6.29 2009
User ID (user) CLONE_NEWUSER 3.8 2013
Control group (cgroup) CLONE_NEWCGROUP 4.6 2016
Time CLONE_NEWTIME 5.6 2020

Mount

挂载点可以在不同命名空间之间共享。

UTS

UNIX Time-Sharing

不知道为什么叫这个名字。作用是隔离主机名和域名。

IPC

不同 IPC 命名空间的进程不能通过 shm 系列方法共享内存。

PID

Network

每个网络命名空间都有一组自己的网络资源,包括 IP 地址、路由表、套接字列表、连接跟踪表、防火墙等等。

User

主要作用是权限的隔离。

Cgroup

进程控制组。

Time

时间的隔离。

系统调用

  • clone
  • unshare
  • setns

参考资料与拓展阅读

#207 Python 加密解密

2017-05-04

#206 英文花体

2017-04-27
| 𝓐 | 𝓑 | 𝓒 | 𝓓 | 𝓔 | 𝓕 | 𝓖 | | :-: | :-: | :-: | :-: | :-: | :-: | :----: | | 𝓗 | 𝓘 | 𝓙 | 𝓚 | 𝓛 | 𝓜 | 𝓝 | | 𝓞 | 𝓟 | 𝓠 | 𝓡 | 𝓢 | 𝓣 |   | | 𝓤 | 𝓥 | 𝓦 | 𝓧 | 𝓨 | 𝓩 |   | | 𝓪 | 𝓫 | 𝓬 | 𝓭 | 𝓮 | 𝓯 | 𝓰 | | 𝓱 | 𝓲 | 𝓳 | 𝓴 | 𝓵 | 𝓶 | 𝓷 | | 𝓸 | 𝓹 | 𝓺 | 𝓻 | 𝓼 | 𝓽 |   | | 𝓾 | 𝓿 | 𝔀 | 𝔁 | 𝔂 | 𝔃 |   |

#205 sdkman 的使用

2017-04-17
# 安装
curl -s "https://get.sdkman.io" | bash

# 查看当前版本
sdk version

# 更新到最新版本
sdk update

# 列出可用 Java 版本
sdk list java

# 安装指定 Java 版本
sdk install java 11.0.16-albba

# 切换到另一个已安装 Java 版本
sdk use java 8.8.9-albba

除了管理 Java 版本,还可以用来管理其他开发工具,比如 Gradle,Maven,Scale 等。

#204 惊群与 accept_mutex

2017-04-16

多个进程共享一个 bind socket 时,会发生这样的情况:一个连接进来,所有相关进程都从睡眠状态被唤醒。然后其中一个进程拿到这个连接,其他进程就继续 sleep。
这种现象就叫做惊群。好处就是如果来了大量连接的话,大家一起干活(可能可以算是正向的影响),坏处就是,如果只来了少量的连接,白白吵醒一众进程,消耗 CPU 资源。
这个好处像没有一样,资源的浪费确是实打实的。

注意,新版本 Nginx 上不需要互斥锁,默认没有惊群现象。

accept_mutex

Syntax: accept_mutex on | off;
Default: accept_mutex off;
Context: events

If accept_mutex is enabled, worker processes will accept new connections by turn. Otherwise, all worker processes will be notified about new connections, and if volume of new connections is low, some of the worker processes may just waste system resources.

There is no need to enable accept_mutex on systems that support the EPOLLEXCLUSIVE flag (1.11.3) or when using reuseport.

Prior to version 1.11.3, the default value was on.

如果 accept_mutex 启用,worker 进程会按顺序接受连接。否则,所有 worker 进程都会收到新连接通知,也就是惊群了。

1.11.3 之前,accept_mutex 默认是 on。为什么现在默认 off 了呢?
文档有写, 因为 1.11.3 之后,支持 EPOLLEXCLUSIVE 标记的平台,默认就不会发生惊群了,不需要 accept_mutex。

此外:如果使用了 TCP reuseport(需要 Linux 内核支持), 就不需要启用 accept_mutex。

如果 reuseport 参考: 2019/02/05, reuseport: 端口复用
PS: 2015/05 发布的 1.9.1 及之后版本,Nginx 引入了 reuseport 指令。

accept_mutex_delay

Syntax: accept_mutex_delay time;
Default: accept_mutex_delay 500ms;
Context: events

If accept_mutex is enabled, specifies the maximum time during which a worker process will try to restart accepting new connections if another worker process is currently accepting new connections.

如果 accept_mutex 启用,那么这个参数指定了 worker 进程申请 accept_mutex 锁失败之后的 sleep 时长。

也就是说如果出现竞争,没有抢到锁的进程就要睡眠一段时间,避免无效的反复申请锁。不过,感觉默认的这个 0.5 秒感觉有点长,50ms 应该就够了吧。

实现

参考:深入浅出 Linux 惊群:现象、原因和解决方案

附: 睡眠队列(等待队列)