時間と期間
時間値、期間、タイムゾーン、スケジューリングを扱う。タイマーの作成、指定期間のスリープ、タイムスタンプの解析とフォーマット。
ワークフローでは、time.now()は決定論的リプレイのために記録された時間参照を返します。
local time = require("time")現在時刻を返す。ワークフローでは、決定論的リプレイのためにワークフローの時間参照から記録された時刻を返す。
local t = time.now()print(t:format_rfc3339()) -- "2024-12-29T15:04:05Z"
-- 経過時間を測定local start = time.now()do_work()local elapsed = time.now():sub(start)print("Took " .. elapsed:milliseconds() .. "ms")戻り値: Time
時間値の作成
Section titled “時間値の作成”コンポーネントから
Section titled “コンポーネントから”-- UTCで特定の日時を作成local t = time.date(2024, time.DECEMBER, 25, 10, 30, 0, 0, time.utc)print(t:format_rfc3339()) -- "2024-12-25T10:30:00Z"
-- 特定のタイムゾーンで作成local ny, _ = time.load_location("America/New_York")local meeting = time.date(2024, time.JANUARY, 15, 14, 0, 0, 0, ny)
-- 指定しない場合はローカルタイムゾーンがデフォルトlocal t = time.date(2024, 1, 15, 12, 0, 0, 0)| パラメータ | 型 | 説明 |
|---|---|---|
year | number | 年 |
month | number | 月(1-12またはtime.JANUARYなど) |
day | number | 日 |
hour | number | 時(0-23) |
minute | number | 分(0-59) |
second | number | 秒(0-59) |
nanosecond | number | ナノ秒(0-999999999) |
location | Location | タイムゾーン(オプション、デフォルトはlocal) |
戻り値: Time
Unixタイムスタンプから
Section titled “Unixタイムスタンプから”-- エポックからの秒数からlocal t = time.unix(1703862245, 0)print(t:utc():format_rfc3339()) -- "2023-12-29T15:04:05Z"
-- ナノ秒付きlocal t = time.unix(1703862245, 500000000) -- +500ms
-- JavaScriptタイムスタンプ(ミリ秒)を変換local js_timestamp = 1703862245000local t = time.unix(js_timestamp // 1000, (js_timestamp % 1000) * 1000000)| パラメータ | 型 | 説明 |
|---|---|---|
sec | number | Unix秒 |
nsec | number | ナノ秒オフセット |
戻り値: Time
Goの参照時刻フォーマットを使用して時刻文字列を解析:Mon Jan 2 15:04:05 MST 2006。
-- RFC3339を解析local t, err = time.parse(time.RFC3339, "2024-12-29T15:04:05Z")if err then return nil, errend
-- カスタムフォーマットを解析local t, err = time.parse("2006-01-02", "2024-12-29")local t, err = time.parse("15:04:05", "14:30:00")local t, err = time.parse("2006-01-02 15:04:05 MST", "2024-12-29 14:30:00 EST")
-- 特定のタイムゾーンで解析local ny, _ = time.load_location("America/New_York")local t, err = time.parse("2006-01-02 15:04", "2024-12-29 14:30", ny)| パラメータ | 型 | 説明 |
|---|---|---|
layout | string | Go時刻フォーマットレイアウト |
value | string | 解析する文字列 |
location | Location | デフォルトタイムゾーン(オプション) |
戻り値: Time, error
Timeメソッド
Section titled “Timeメソッド”local t = time.now()
-- 期間を追加(数値、文字列、またはDurationを受け付け)local tomorrow = t:add("24h")local later = t:add(5 * time.MINUTE)local d, _ = time.parse_duration("1h30m")local future = t:add(d)
-- 時間を減算して期間を取得local diff = tomorrow:sub(t) -- Durationを返すprint(diff:hours()) -- 24
-- カレンダー単位を追加(月境界を正しく処理)local next_month = t:add_date(0, 1, 0) -- 1ヶ月追加local next_year = t:add_date(1, 0, 0) -- 1年追加local last_week = t:add_date(0, 0, -7) -- 7日減算| メソッド | パラメータ | 戻り値 | 説明 |
|---|---|---|---|
add(duration) | number/string/Duration | Time | 期間を追加 |
sub(time) | Time | Duration | 時間の差分 |
add_date(years, months, days) | numbers | Time | カレンダー単位を追加 |
local t1 = time.date(2024, 1, 1, 0, 0, 0, 0, time.utc)local t2 = time.date(2024, 1, 2, 0, 0, 0, 0, time.utc)
t1:before(t2) -- truet2:after(t1) -- truet1:equal(t1) -- true| メソッド | パラメータ | 戻り値 | 説明 |
|---|---|---|---|
before(time) | Time | boolean | この時間は他より前か? |
after(time) | Time | boolean | この時間は他より後か? |
equal(time) | Time | boolean | 時間は等しいか? |
フォーマット
Section titled “フォーマット”local t = time.now()
t:format_rfc3339() -- "2024-12-29T15:04:05Z"t:format(time.DATE_ONLY) -- "2024-12-29"t:format(time.TIME_ONLY) -- "15:04:05"t:format("Mon Jan 2, 2006") -- "Sun Dec 29, 2024"| メソッド | パラメータ | 戻り値 | 説明 |
|---|---|---|---|
format(layout) | string | string | Goレイアウトでフォーマット |
format_rfc3339() | - | string | RFC3339としてフォーマット |
Unixタイムスタンプ
Section titled “Unixタイムスタンプ”local t = time.now()
t:unix() -- エポックからの秒数t:unix_nano() -- エポックからのナノ秒コンポーネント
Section titled “コンポーネント”local t = time.now()
-- 日付部分を取得local year, month, day = t:date()
-- 時刻部分を取得local hour, min, sec = t:clock()
-- 個別のアクセサt:year() -- 例:2024t:month() -- 1-12t:day() -- 1-31t:hour() -- 0-23t:minute() -- 0-59t:second() -- 0-59t:nanosecond() -- 0-999999999t:weekday() -- 0=日曜 .. 6=土曜t:year_day() -- 1-366t:is_zero() -- ゼロ値の場合trueタイムゾーン変換
Section titled “タイムゾーン変換”local t = time.now()
t:utc() -- UTCに変換t:in_local() -- ローカルタイムゾーンに変換t:in_location(ny) -- 特定のタイムゾーンに変換t:location() -- 現在のLocationを取得t:location():string() -- タイムゾーン名を取得| メソッド | パラメータ | 戻り値 | 説明 |
|---|---|---|---|
utc() | - | Time | UTCに変換 |
in_local() | - | Time | ローカルタイムゾーンに変換 |
in_location(loc) | Location | Time | タイムゾーンに変換 |
location() | - | Location | 現在のタイムゾーンを取得 |
期間境界に丸めまたは切り捨て。Duration userdataが必要(数値や文字列ではない)。
local t = time.now()local hour_duration, _ = time.parse_duration("1h")local minute_duration, _ = time.parse_duration("15m")
t:round(hour_duration) -- 最も近い時間に丸めt:truncate(minute_duration) -- 15分境界に切り捨て| メソッド | パラメータ | 戻り値 | 説明 |
|---|---|---|---|
round(duration) | Duration | Time | 最も近い倍数に丸め |
truncate(duration) | Duration | Time | 倍数に切り捨て |
Duration
Section titled “Duration”Durationの作成
Section titled “Durationの作成”-- 文字列から解析local d, err = time.parse_duration("1h30m45s")local d, err = time.parse_duration("500ms")local d, err = time.parse_duration("2h30m45s500ms")
-- 数値から(ナノ秒)local d, err = time.parse_duration(time.SECOND)local d, err = time.parse_duration(5 * time.MINUTE)
-- 有効な単位: ns, us, ms, s, m, h| パラメータ | 型 | 説明 |
|---|---|---|
value | number/string/Duration | 解析する期間 |
戻り値: Duration, error
Durationメソッド
Section titled “Durationメソッド”local d, _ = time.parse_duration("1h30m45s500ms")
d:hours() -- 1.5125...d:minutes() -- 90.75...d:seconds() -- 5445.5d:milliseconds() -- 5445500d:microseconds() -- 5445500000d:nanoseconds() -- 5445500000000タイムゾーン
Section titled “タイムゾーン”名前でロード
Section titled “名前でロード”IANA名でタイムゾーンをロード(例:“America/New_York”、“Europe/London”、“Asia/Tokyo”)。
local ny, err = time.load_location("America/New_York")if err then return nil, errend
local tokyo, _ = time.load_location("Asia/Tokyo")local london, _ = time.load_location("Europe/London")
-- タイムゾーン間で変換local t = time.now():utc()print("UTC:", t:format(time.TIME_ONLY))print("New York:", t:in_location(ny):format(time.TIME_ONLY))print("Tokyo:", t:in_location(tokyo):format(time.TIME_ONLY))| パラメータ | 型 | 説明 |
|---|---|---|
name | string | IANAタイムゾーン名 |
戻り値: Location, error
固定オフセット
Section titled “固定オフセット”固定UTCオフセットでタイムゾーンを作成。
-- UTC+5:30(インド標準時)local ist = time.fixed_zone("IST", 5*3600 + 30*60)
-- UTC-8(太平洋標準時)local pst = time.fixed_zone("PST", -8*3600)
local t = time.date(2024, 1, 15, 12, 0, 0, 0, ist)| パラメータ | 型 | 説明 |
|---|---|---|
name | string | ゾーン名 |
offset | number | 秒単位のUTCオフセット |
戻り値: Location
組み込みLocation
Section titled “組み込みLocation”time.utc -- UTCタイムゾーンtime.localtz -- ローカルシステムタイムゾーンスケジューリング
Section titled “スケジューリング”指定期間だけ実行を一時停止。ワークフローでは、正しく記録・リプレイされます。
time.sleep("5s")time.sleep(500 * time.MILLISECOND)
-- バックオフパターンfor attempt = 1, 3 do local ok = try_operation() if ok then break end time.sleep(tostring(attempt) .. "s")end| パラメータ | 型 | 説明 |
|---|---|---|
duration | number/string/Duration | スリープ時間 |
期間後に一度受信するチャネルを返す。channel.selectと連携。
-- シンプルなタイムアウトlocal timeout = time.after("5s")timeout:receive() -- 5秒間ブロック
-- selectでタイムアウトlocal response_ch = make_request()local timeout_ch = time.after("30s")
local result = channel.select{ response_ch:case_receive(), timeout_ch:case_receive()}
if result.channel == timeout_ch then return nil, errors.new({message = "Request timed out", kind = errors.TIMEOUT})end| パラメータ | 型 | 説明 |
|---|---|---|
duration | number/string/Duration | 待機時間 |
戻り値: Channel
期間後に発火するワンショットタイマー。停止またはリセット可能。
local timer = time.timer("5s")
-- タイマーを待機timer:response():receive()send_reminder()
-- アクティビティでリセットlocal idle_timer = time.timer("5m")while true do local r = channel.select{ user_activity:case_receive(), idle_timer:response():case_receive() } if r.channel == idle_timer:response() then logout_user() break end idle_timer:reset("5m")end
-- タイマーを停止timer:stop()| パラメータ | 型 | 説明 |
|---|---|---|
duration | number/string/Duration | 発火までの時間 |
戻り値: Timer, error
| Timerメソッド | パラメータ | 戻り値 | 説明 |
|---|---|---|---|
response() | - | Channel | タイマーチャネルを取得 |
channel() | - | Channel | response()のエイリアス |
stop() | - | boolean | タイマーをキャンセル |
reset(duration) | number/string/Duration | boolean | 新しい期間でリセット |
ticker
Section titled “ticker”定期的な間隔で発火する繰り返しタイマー。
-- 定期タスクlocal ticker = time.ticker("30s")local ch = ticker:response()
while true do local tick_time = ch:receive() check_health()end
-- レート制限local ticker = time.ticker("100ms")for _, item in ipairs(items) do ticker:response():receive() process(item)endticker:stop()| パラメータ | 型 | 説明 |
|---|---|---|
duration | number/string/Duration | ティック間の間隔 |
戻り値: Ticker, error
| Tickerメソッド | パラメータ | 戻り値 | 説明 |
|---|---|---|---|
response() | - | Channel | tickerチャネルを取得 |
channel() | - | Channel | response()のエイリアス |
stop() | - | boolean | tickerを停止 |
期間定数はナノ秒単位。算術で使用。
time.NANOSECOND -- 1time.MICROSECOND -- 1,000time.MILLISECOND -- 1,000,000time.SECOND -- 1,000,000,000time.MINUTE -- 60 * SECONDtime.HOUR -- 60 * MINUTE
-- 使用例time.sleep(5 * time.SECOND)local timeout = time.after(30 * time.SECOND)フォーマットレイアウト
Section titled “フォーマットレイアウト”time.RFC3339 -- "2006-01-02T15:04:05Z07:00"time.RFC3339NANO -- "2006-01-02T15:04:05.999999999Z07:00"time.RFC822 -- "02 Jan 06 15:04 MST"time.RFC822Z -- "02 Jan 06 15:04 -0700"time.RFC850 -- "Monday, 02-Jan-06 15:04:05 MST"time.RFC1123 -- "Mon, 02 Jan 2006 15:04:05 MST"time.RFC1123Z -- "Mon, 02 Jan 2006 15:04:05 -0700"time.DATE_TIME -- "2006-01-02 15:04:05"time.DATE_ONLY -- "2006-01-02"time.TIME_ONLY -- "15:04:05"time.KITCHEN -- "3:04PM"time.STAMP -- "Jan _2 15:04:05"time.STAMP_MILLI -- "Jan _2 15:04:05.000"time.STAMP_MICRO -- "Jan _2 15:04:05.000000"time.STAMP_NANO -- "Jan _2 15:04:05.000000000"time.JANUARY -- 1time.FEBRUARY -- 2time.MARCH -- 3time.APRIL -- 4time.MAY -- 5time.JUNE -- 6time.JULY -- 7time.AUGUST -- 8time.SEPTEMBER -- 9time.OCTOBER -- 10time.NOVEMBER -- 11time.DECEMBER -- 12time.SUNDAY -- 0time.MONDAY -- 1time.TUESDAY -- 2time.WEDNESDAY -- 3time.THURSDAY -- 4time.FRIDAY -- 5time.SATURDAY -- 6| 条件 | 種別 | 再試行可能 |
|---|---|---|
| 無効な期間フォーマット | errors.INVALID | no |
| 解析失敗 | errors.INTERNAL | no |
| 空のlocation名 | errors.INVALID | no |
| Locationが見つからない | errors.INTERNAL | no |
| Duration <= 0(timer/ticker) | errors.INVALID | no |
local t, err = time.parse(time.RFC3339, "invalid")if err then if errors.is(err, errors.INVALID) then print("Invalid format:", err:message()) end return nil, errend
local loc, err = time.load_location("Unknown/Zone")if err then if errors.is(err, errors.INTERNAL) then print("Location not found:", err:message()) end return nil, errendエラーの処理についてはエラー処理を参照。