普贤教程 › 进阶教程
时间与日期
PuXian 的时间底层就是整数时间戳。这里有一个必须提前知道的事实:time_format 按 UTC 输出,要本地时间得再换算一次。
拿时间
px
print(str(now_sec() > 1700000000)) print(str(now_ms() > 1700000000000)) print(now())
text
true true 2026-11-05 17:06:52
| 函数 | 返回 | 时区 |
|---|---|---|
now_sec() | 秒级时间戳(int) | — |
now_ms() | 毫秒级时间戳(int) | — |
now() | 格式化字符串 %Y-%m-%d %H:%M:%S | 本地 |
time_format(sec, fmt) | 按格式串输出 | UTC |
时区:最容易出错的地方
px
print(now()) # 本地 print(time_format(now_sec(), "%Y-%m-%d %H:%M:%S")) # UTC
text
2026-11-05 17:06:52 2026-11-05 09:06:52
同一时刻,两个函数差 8 小时。time_format 固定按 UTC 解释时间戳,不受 TZ 环境变量影响。要本地时间,三条路:
| 做法 | 写法 |
|---|---|
| 直接取现成字符串 | now() |
| 时间戳 + 时区偏移格式化 | dt_to_timezone(sec, 8 * 3600) |
| 用 Go 风格格式化 | import std.time_go → go_date_time(sec) |
px
import std.time_go
print(go_date_time(now_sec()))
print(go_rfc3339(now_sec()))text
2026-11-05 17:06:52 2026-11-05T17:06:52+08:00
写日志时想清楚用哪个日志用 UTC 便于跨机器对齐,展示给用户用本地。混用会造成"日志里是 09:06,用户说是 17:06 出的问题"这种排查灾难。建议:日志统一 UTC 并标注
Z。格式化符
| 格式 | 含义 |
|---|---|
%Y %m %d | 年(4 位)/ 月 / 日 |
%H %M %S | 时 / 分 / 秒(24 小时制) |
%Y-%m-%d | 2026-11-05 |
%H:%M | 17:06 |
日期运算
时间戳是整数,加减就是算术。一天固定 86400 秒:
px
var t = now_sec() var day = 86400 print(time_format(t + day, "%m-%d")) print(time_format(t - 7 * day, "%m-%d"))
text
11-06 10-29
更规范的做法是用 datetime 包,它把"加天数、算差值、判闰年"都封好了:
sh
pxpkg add datetime@0.2.0 && pxpkg install
px
import datetime var t = dt_now_sec() print(dt_format(t, "%Y-%m-%d")) # UTC print(dt_to_timezone(t, 8 * 3600)) # 本地 print(dt_format(dt_add_days(t, 30), "%Y-%m-%d")) print(str(dt_days_between(t, dt_add_days(t, 30)))) print(dt_humane(t, t - 180))
text
2026-11-05 2026-11-05 17:06:52 2026-12-05 30 3分钟前
| 函数 | 作用 |
|---|---|
dt_now_sec() | 当前秒级时间戳(dt_now() 返回的是字符串,别混) |
dt_format(sec, fmt) | 格式化(UTC) |
dt_to_timezone(sec, off_sec) | 按偏移格式化,如 8 * 3600 |
dt_parse(s, fmt) / dt_iso_parse(s) | 解析字符串 |
dt_add_days(sec, n) / dt_add(sec, delta) | 加减 |
dt_days_between(a, b) / dt_diff | 差值 |
dt_weekday(y, m, d) / dt_week_of_year / dt_quarter | 星期 / 周数 / 季度 |
dt_is_leap_year / dt_days_in_month | 闰年、月天数 |
dt_humane(now, then) | "3分钟前"这类相对描述 |
dt_duration_parse("1h30m") / dt_duration_format(sec) | 时长解析与格式化 |
测耗时
px
var t0 = now_ms() var sum = 0 for i in range(0, 100000): sum += i print("耗时 " + str(now_ms() - t0) + " ms")
text
耗时 5374 ms同一个程序编译后是 11 ms上面这段在解释轨跑 5 秒多(三次 5182–5928 ms),
px build 出来的二进制 10–12 毫秒(默认 VM 字节码轨;--c 的 C 轨 4–5 ms)。测性能前先确认自己跑的是哪条轨。常见坑
| 现象 | 原因 |
|---|---|
| 时间差 8 小时 | time_format 是 UTC;要本地用 now() 或 dt_to_timezone |
| 年份 5 万多 | 把毫秒时间戳传给了按秒的函数 |
dt_now() 传给 dt_format 报"无法转为 int" | dt_now() 返回字符串,应该用 dt_now_sec() |
| 跨月天数算错 | 用 30 天近似;改用 dt_days_between |