Rの日時データ #2 - 文字列⇔日時オブジェクトの変換
はじめに
Rの日時データ[1]に関する記事#2です。
今回は文字列⇔日時オブジェクト[1:1]の変換手順についてです。
文字列と日時オブジェクト(POSIXct型のオブジェクト)の変換として、
- 変換方向(文字列→日時オブジェクト or 日時オブジェクト→文字列)
- 文字列に明示的にタイムゾーン情報があるか(あり(ISO8601形式) or なし)
によって、以下の4つの手順に分けて説明します。
| タイムゾーン情報あり | タイムゾーン情報なし | |
|---|---|---|
| 文字列→日時オブジェクト | 1 | 2 |
| 日時オブジェクト→文字列 | 3 | 4 |
1. 文字列→日時オブジェクト(タイムゾーン情報あり)
タイムゾーン情報が明示的に指定された文字列(ISO8601形式)を日時オブジェクト(POSIXct型のオブジェクト)に変換するには、#1で紹介したlubridate::ymd_hms関数を使うと良いでしょう。
> lubridate::ymd_hms("2022-11-24T00:30:38+09:00")
[1] "2022-11-23 15:30:38 UTC"
> lubridate::ymd_hms("2022-11-24T00:30:38Z")
[1] "2022-11-24 00:30:38 UTC"
>
lubridate::ymd_hms関数を使用することで、ISO8601形式であればどのタイムゾーンの文字列であっても問題なく変換することができます。
2. 文字列→日時オブジェクト(タイムゾーン情報なし)
タイムゾーンの指定がない場合は、必ず仕様を確認し、as.POSIXct関数のtz引数を指定することが必要です。
> as.POSIXct("2011-03-20 12:34:56", tz="UTC")
[1] "2011-03-20 12:34:56 UTC"
> as.POSIXct("2011-03-20 12:34:56", tz="Asia/Tokyo")
[1] "2011-03-20 12:34:56 JST"
>
tz引数を指定しないと、#1で紹介したように、実行環境のシステムのタイムゾーンに依存した日時オブジェクトが作成されてしまいます。
> as.POSIXct("2011-03-20 12:34:56")
[1] "2011-03-20 12:34:56 JST"
>
3. 日時オブジェクト→文字列(タイムゾーン情報あり)
日時オブジェクト(POSIXct型のオブジェクト)からタイムゾーン情報ありのISO8601形式にするには、以下の3つの方法があります。用途と出力形式が微妙に異なるので、状況に応じて使い分けると良いでしょう。
format/strftime関数(%z記法)
baseライブラリのformat関数やstrftime関数を使う方法です。
format関数のtz引数にタイムゾーンを指定し、フォーマット文字列に%zを指定することで、タイムゾーンを示す文字列(+0900)を追加できます。但し、ここで追加される+0900はISO8601の基本形式と呼ばれるもの(:が付いていないもの)になっている点に注意が必要です。また、UTCの場合にZでなく+0000になってしまう点にも注意が必要でしょう。
> d <- as.POSIXct("2011-03-20 12:34:56", tz="Asia/Tokyo")
> format(d, "%Y-%m-%dT%H:%M:%S%z", tz="Asia/Tokyo")
[1] "2011-03-20T12:34:56+0900"
> format(d, "%Y-%m-%dT%H:%M:%S%z", tz="UTC")
[1] "2011-03-20T03:34:56+0000"
>
format/strftime関数(固定タイムゾーン文字列指定)
+0900や+0000でなく、+09:00やZに変換したい場合には、あまり美しくないですが、フォーマット文字列に指定するしか無いようです。
> d <- as.POSIXct("2011-03-20 12:34:56", tz="Asia/Tokyo")
> format(d, "%Y-%m-%dT%H:%M:%S+09:00", tz="Asia/Tokyo")
[1] "2011-03-20T12:34:56+09:00"
> format(d, "%Y-%m-%dT%H:%M:%SZ", tz="UTC")
[1] "2011-03-20T03:34:56Z"
>
lubridate::format_ISO8601関数
日時オブジェクト(POSIXct型のオブジェクト)で保持されたタイムゾーンに応じて出力されるタイムゾーンを変えたい場合は、lubridate::format_ISO8601関数を使うと良いでしょう。
> d <- as.POSIXct("2011-03-20 12:34:56", tz="Asia/Tokyo")
> format_ISO8601(d, usetz = TRUE)
[1] "2011-03-20T12:34:56+0900"
> d <- with_tz(d, tzone = "UTC")
> format_ISO8601(d, usetz = TRUE)
[1] "2011-03-20T03:34:56+0000"
>
動作はフォーマット文字列に%zを使用した場合と同じで、:が付いてなく、Zに変換されない点に注意が必要です。
4. 日時オブジェクト→文字列(タイムゾーン情報なし)
"2011-03-20 12:34:56"のようなタイムゾーン情報なしの文字列に変換するには、baseライブラリのformat関数やstrftime関数を使えば可能です。
> d <- as.POSIXct("2011-03-20 12:34:56", tz="Asia/Tokyo")
> format(d, "%Y-%m-%d %H:%M:%S", tz="Asia/Tokyo")
[1] "2011-03-20 12:34:56"
> format(d, "%Y-%m-%d %H:%M:%S", tz="Europe/Paris")
[1] "2011-03-20 04:34:56"
> strftime(d, "%Y-%m-%d %H:%M:%S", tz="Asia/Tokyo")
[1] "2011-03-20 12:34:56"
> strftime(d, "%Y-%m-%d %H:%M:%S", tz="Europe/Paris")
[1] "2011-03-20 04:34:56"
>
この場合も、tz引数は付けたほうがコードの意図が明確になって親切だと思います。
以下のように、tz引数無しで呼び出した場合、タイムゾーンに依存せず時刻の情報のみで文字列が生成されるようです。
> d <- as.POSIXct("2011-03-20 12:34:56", tz="Asia/Tokyo")
> format(d, "%Y-%m-%d %H:%M:%S")
[1] "2011-03-20 12:34:56"
> d <- as.POSIXct("2011-03-20 12:34:56", tz="UTC")
> format(d, "%Y-%m-%d %H:%M:%S")
[1] "2011-03-20 12:34:56"
>
まとめ
今回は、文字列⇔日時オブジェクトの変換について4つの場合に分けて紹介しました。
次回の#3は、csvファイルの読み書きと日時オブジェクト(POSIXct型のオブジェクト)について書きたいと思います。
Discussion