tech.guitarrapc.cóm

Technical updates

PowerShellで日付書式にカスタム書式パターンを指定する

以前、Get-Dateコマンドレットで出力される標準書式について記事を書きました。

PowerShellのGet-Date -Formatで出力される標準の書式指定結果一覧

今回は、PowerShellでDateTime型にキャストする際、PowerShellでのカスタム書式指定についてみていきます。

日付を取得する

繰り返しになりますが、PowerShellで日付を取得する方法をみてみます。

コマンドレットで日付を取得する

何も指定しなければ、本日が取得できます。

PS> Get-Date
20132910:36:09

結果に対して、.AddDays.AddMonthsなどで対象プロパティを操作もできます。 例えば取得結果から、一日進めるならこうです。

PS> (Get-Date).AddDays(1)

201321010:39:13

.NETで日付を取得する

これで本日が取得できます。

PS> [System.DateTime]::Now
20132910:41:52

[System.DateTime][DateTime]に短縮できます。 日付のみを取得するなら、Todayメソッドを利用してかけます。

PS> [DateTime]::Today
2013290:00:00

文字列を日付型にキャストする

文字列から日付型へのキャスト(型変換)をみてみます。

暗黙の型変換

1つは、「DateTimeにしなさい」と指定する方法です。 この場合は、PowerShellがDateTime型に変換するため理解できる書式である必要があります。 例えばこうです。

PS> [DateTime]"2013/02/09"
2013290:00:00

PS> [DateTime]"2013/02/09 13:59:50"
20132913:59:50

では、どこが年月日か不明な場合は怒られます。

PS> [DateTime]"20130209""20130209" を型 "System.DateTime" に変換できません。エラー: "文字列は有効な DateTime ではありませんでした。"
発生場所 D:\Test.ps1:11 文字:1
+ [DateTime]"20130209"
+ ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) []、RuntimeException
    + FullyQualifiedErrorId : InvalidCastParseTargetInvocationWithFormatProvider

[System.Datetime]::Parse()メソッドでの型変換

.Netの[System.Datetime]::Parse()メソッドを利用する方法もあります。 暗黙の型変換と同様の結果となります。

PS> [Datetime]::Parse("2013/02/09")
2013290:00:00

PS> [Datetime]::Parse("2013/02/09 13:59:50")
20132913:59:50

こちらも、どこが年月日か不明な場合も怒られます。

PS> [Datetime]::Parse(20130209")
値 "20130209" を型 "System.DateTime" に変換できません。エラー: "文字列は有効な DateTime ではありませんでした。"
発生場所 D:\Test.ps1:11 文字:1
+ [DateTime]"20130209"
+ ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) []、RuntimeException
    + FullyQualifiedErrorId : InvalidCastParseTargetInvocationWithFormatProvider

カスタム書式を指定する

では、カスタム日付を指定してみましょう。 まず、カスタム書式を指定するに当たり、何はともあれ知っておきましょう。 カスタムの日付と時刻の書式指定文字列

コマンドレットでカスタム書式を指定する

標準書式と同様に、-Formatで書式を指定できます。 例えばyyyyMMdd_hhmmssというフォーマットを指定します。

PS> Get-Date -Format "yyyyMMdd_HHmmss"
20130209_105156

上記の-Formatメソッドを利用した書き方は、.ToString()メソッドと同等です。

PS> (Get-Date).ToString("yyyyMMdd_HHmmss")
20130209_105156

先ほどの[Datetime]型への変換と、ToString()を組み合わせて、元の文字列の書式を変えることもできますね。 用途があるかは不明ですが。

PS> ([DateTime]"2013/02/09 13:59:50").ToString("yyyyMMdd_HHmmss")
20130209_135950

.Netでカスタム書式を指定する

[DateTime]::ParseExact()メソッドを利用します。 MSDNの注意に気を付けましょう。

DateTime.ParseExact メソッド (String, String, IFormatProvider).aspx)

指定した書式とカルチャ固有の書式情報を使用して、指定した日付と時刻の文字列形式を等価のDateTimeの値に変換します。文字列形式の書式は、指定した書式と完全に一致する必要があります。結果はSystemの国別書式に合わせられていますね。 設定が、日本語(ja-JP)なので年月日となっています。

PS> [DateTime]::ParseExact("12/11/2012 13:59:51","dd/MMM/yyyy HH:mm:ss",$null)
2012111213:59:51

もちろん.ToString()メソッドで書式指定もできます。

PS> [DateTime]::ParseExact("12/11/2012 13:59:51","dd/MMM/yyyy HH:mm:ss",$null).ToString("dd/MMM/yyyy HH:mm:ss"
12/11/2012 13:59:51

[DateTime]::ParseExact利用のメリット

[DateTime]::ParseExact()であれば、読み取り時、書式ヒントを与えられます。そのため、コマンドレットや[System.Datetime]::Parse()よりも柔軟に書式指定ができます。 逆に、指定した書式パターンでないとExcenption(例外)を返すため、曖昧な読み取りも防げます。例えば、起こられた[DateTime]"20130209"を読み取らせるには…。

PS> [DateTime]::ParseExact("20130209","yyyyMMdd",$null)
2013290:00:00

[DateTime]::ParseExact利用時の注意

問題があるようなので注意しましょう。

DateTime.ParseExactメソッドで、1900年代の日時に変換される

PS> [DateTime]::ParseExact("301112 13:59:51","yyMMdd HH:mm:ss",[System.Globalization.CultureInfo]::InvariantCulture)
1930111213:59:51

IFormatProviderで出力するカルチャ指定する

[DateTime]::ParseExact()を利用する際は、きっちり分かっておく必要がありますね。

IFormatProvider インターフェース.aspx)

特に依存を指定しない場合は、IFormatProvider[System.Globalization.CultureInfo]::InvariantCultureを指定します。これで、カルチャに依存しない (インバリアントな) CultureInfoを取得できます。

CultureInfo.InvariantCulture プロパティ.aspx)

試してみましょう。

PS> [DateTime]::ParseExact("20121112 13:59:51","yyyyMMdd HH:mm:ss",[System.Globalization.CultureInfo]::InvariantCulture)
2012111213:59:51

基本的にPowerShellにおいては、$null[System.Globalization.CultureInfo]::InvariantCulture)を指定しておくことで、現在のスケールで出力されます。

まとめ

PowerShellでのカスタム日付指定は、単純なパターンであれば[DateTime]で型変換して.ToString()メソッドで指定にて問題ないでしょう。ただ、[DateTime]::ParseExact()を利用することで、柔軟な読み取りパターン指定ができます。

次回は、[DateTime]::ParseExact()にて国(Culture)を指定する方法を紹介します。

参考サイト