Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

补充日期函数的基础使用方法 #315

Merged
merged 2 commits into from
Jan 5, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 81 additions & 7 deletions lua/time_date_function.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,86 @@

在 Lua 中,函数 `time`、`date` 和 `difftime` 提供了所有的日期和时间功能。

在 OpenResty 的世界里,**不推荐** 使用这里的标准时间函数,因为这些函数通常会引发不止一个昂贵的系统调用,同时无法为 LuaJIT JIT 编译,对性能造成较大影响。
### (推荐)基于缓存的 ngx_lua 时间接口

事实上,在 Nginx/Openresty 中,会经常使用到获取时间操作,通常一次请求最少有几十次获取时间操作,当单核心 RPS/QPS 达到 10K 以上时,获取时间操作往往会达到 200K+量级的调用,是一个非常高频的调用。所以 Nginx 会将时间和日期进行缓存,并非每次调用或每次请求获取时间和日期。

**推荐** 使用 ngx_lua 模块提供的带缓存的时间接口,如 `ngx.today`, `ngx.time`, `ngx.utctime`,
`ngx.localtime`, `ngx.now`, `ngx.http_time`,以及 `ngx.cookie_time` 等。

#### ngx.today()

语法:`str = ngx.today()`

该接口从 Nginx 缓存的时间中获取时间,返回当前的时间和日期,其格式为`yyyy-mm-dd`(与 Lua 的日期库不同,不涉及系统调用)。

#### ngx.time()

语法:`secs = ngx.time()`

该接口从 Nginx 缓存的时间中获取时间,返回当前时间戳的历时秒数(与 Lua 的日期库不同,不涉及系统调用)。

#### ngx.now()

语法:`secs = ngx.now()`

该接口从 Nginx 缓存的时间中获取时间,以秒为单位(包括小数部分的毫秒)返回从当前时间戳开始的浮点数(与 Lua 的日期库不同,不涉及系统调用)。

> ngx.time() 和 ngx.now() 辨析:ngx.time() 获取到的是秒级时间,ngx.now() 获取到的是毫秒级时间。

#### ngx.localtime()

语法:`str = ngx.localtime()`

返回 Nginx 缓存时间的当前时间戳(格式为 `yyy-mm-dd hh:mm:ss`)(与 Lua 的日期库不同,不涉及系统调用)。

#### ngx.utctime()

语法:`str = ngx.utctime()`

返回 Nginx 缓存时间的当前 UTC 时间戳(格式为 `yyyy-mm-dd hh:mm:ss`)(与 Lua 的日期库不同,不涉及系统调用)。

#### ngx.update_time()

语法:`ngx.update_time()`

强制更新 Nginx 当前时间缓存。这个调用涉及到一个系统调用,因此有一些开销,所以不要滥用。

#### 获取时间示例代码

>示例代码:
```lua
ngx.log(ngx.INFO, ngx.today())
ngx.log(ngx.INFO, ngx.time())
ngx.log(ngx.INFO, ngx.now())
ngx.log(ngx.INFO, ngx.localtime())
ngx.log(ngx.INFO, ngx.utctime())

ngx.update_time()

ngx.log(ngx.INFO, ngx.today())
ngx.log(ngx.INFO, ngx.time())
ngx.log(ngx.INFO, ngx.now())
ngx.log(ngx.INFO, ngx.localtime())
ngx.log(ngx.INFO, ngx.utctime())

-->output
2020/12/31 15:37:27 [error] 15851#0: *2153324: 2020-12-31
2020/12/31 15:37:27 [error] 15851#0: *2153324: 1609400247
2020/12/31 15:37:27 [error] 15851#0: *2153324: 1609400247.704 --**
2020/12/31 15:37:27 [error] 15851#0: *2153324: 2020-12-31 15:37:27
2020/12/31 15:37:27 [error] 15851#0: *2153324: 2020-12-31 07:37:27
2020/12/31 15:37:27 [error] 15851#0: *2153324: 2020-12-31
2020/12/31 15:37:27 [error] 15851#0: *2153324: 1609400247
2020/12/31 15:37:27 [error] 15851#0: *2153324: 1609400247.705 --缓存时间有变化
2020/12/31 15:37:27 [error] 15851#0: *2153324: 2020-12-31 15:37:27
2020/12/31 15:37:27 [error] 15851#0: *2153324: 2020-12-31 07:37:27
```

### (不推荐) Lua 自带的日期和时间函数

在 OpenResty 的世界里,**不推荐** 使用这里的标准时间函数,因为这些函数通常会引发不止一个昂贵的系统调用,同时无法为 LuaJIT JIT 编译,对性能造成较大影响。

所以下面的部分函数,简单了解一下即可。

#### os.time ([table])
Expand All @@ -25,7 +100,7 @@ table 的字段如下:
|hour|0--23|
|min|0--59|
|sec|0--61|
|isdst|boolean(true表示夏令时)|
|isdst|boolean(true 表示夏令时)|

对于 `time` 函数,如果参数为 table,那么 table 中 **必须** 含有 year、month、day 字段。其他字段缺省时,默认为中午(12:00:00)。

Expand All @@ -41,7 +116,7 @@ print(os.time(a)) -->output 60

返回 t1 到 t2 的时间差,单位为秒。

>示例代码:
>示例代码

```lua
local day1 = { year = 2015, month = 7, day = 30 }
Expand Down Expand Up @@ -74,7 +149,6 @@ end
ans1 = ans1 .. "}"
print("tab1 = ", ans1)


local tab2 = os.date("*t", 360) --返回一个描述日期和时间数为 360 秒的表
local ans2 = "{"
for k, v in pairs(tab2) do --把 tab2 转换成一个字符串
Expand Down Expand Up @@ -102,14 +176,14 @@ tab2 = { hour = 8, min = 6, wday = 5, day = 1, month = 1, year = 1970, sec = 0,
|%B|月份的全称(例如:September)|
|%c|日期和时间(例如:07/30/15 16:57:24)|
|%d|一个月中的第几天 [01 ~ 31]|
|%H|24小时制中的小时数 [00 ~ 23]|
|%I|12小时制中的小时数 [01 ~ 12]|
|%H|24 小时制中的小时数 [00 ~ 23]|
|%I|12 小时制中的小时数 [01 ~ 12]|
|%j|一年中的第几天 [001 ~ 366]|
|%M|分钟数 [00 ~ 59]|
|%m|月份数 [01 ~ 12]|
|%p|“上午(am)”或“下午(pm)”|
|%S|秒数 [00 ~ 59]|
|%w|一星期中的第几天[1 ~ 7 = 星期天 ~ 星期六]|
|%w|一星期中的第几天 [1 ~ 7 = 星期天 ~ 星期六]|
|%x|日期(例如:07/30/15)|
|%X|时间(例如:16:57:24)|
|%y|两位数的年份 [00 ~ 99]|
Expand Down