🌎

Rの日時データ #2 - 文字列⇔日時オブジェクトの変換

2022/12/16に公開約4,800字

はじめに

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:00Zに変換したい場合には、あまり美しくないですが、フォーマット文字列に指定するしか無いようです。

> 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型のオブジェクト)について書きたいと思います。

脚注
  1. 「日時データ」や「日時オブジェクト」といった用語は、野間口謙太郎, 菊池泰樹 訳 「統計学:Rを用いた入門書 第2版」共立出版 2016 pp.348-349 を参考にしています。 ↩︎ ↩︎

GitHubで編集を提案

Discussion

ログインするとコメントできます