tech.guitarrapc.cóm

Technical updates

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

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

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

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

日付を取得する

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

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

まずは、コマンドレットといえばこれです。

Get-Date

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

2013年2月9日 10:36:09

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

(Get-Date).AddDays(1)

一日進みました。

201321010:39:13

.Netで日付を取得する

簡単ですね。

[System.DateTime]::Now

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

20132910:41:52

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

2013290:00:00

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

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

暗黙の型変換

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

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

上手く認識できました。

2013290:00:00
20132913:59:50

では、どこが年月日か不明な場合はどうなるでしょうか。

[DateTime]"20130209"

"文字列は有効な DateTime ではありませんでした。"と怒られてしまいますね。

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

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

.Netの[System.Datetime]::Parse()メソッドを利用する方法もあります。 先ほどのコードはこのようになります。

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

暗黙の型変換と同様の結果となります。

2013290:00:00
20132913:59:50

こちらも、どこが年月日か不明な場合はどうなるでしょうか。

[Datetime]::Parse(20130209")

怒られますね。

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

カスタム書式を指定する

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

カスタムの日付と時刻の書式指定文字列

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

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

Get-Date -Format "yyyyMMdd_HHmmss"

すると指定した書式の[string]型が出力されます。

20130209_105156

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

(Get-Date).ToString("yyyyMMdd_HHmmss")

結果も同じですね。

20130209_105156

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

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

結果はこうです。

20130209_135950

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

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

DateTime.ParseExact メソッド (String, String, IFormatProvider) 指定した書式とカルチャ固有の書式情報を使用して、指定した日付と時刻の文字列形式を等価の DateTime の値に変換します。文字列形式の書式は、指定した書式と完全に一致する必要があります。

例えばこうです。

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

結果は…Systemの国別書式に合わせられていますね。 設定が、日本語(ja-JP)なので年月日となっています。

2012111213:59:51

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

[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"を読み取らせるには…。

[DateTime]::ParseExact("20130209","yyyyMMdd",$null)

無事に読み取れました。

2013290:00:00

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

どうやら、この問題があるようなので注意しましょう。

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

テストします。

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

確かに問題ですね…。

1930111213:59:51

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

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

IFormatProvider インターフェイス

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

CultureInfo.InvariantCulture プロパティ

試してみましょう。

[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)を指定する方法を紹介します。

参考サイト

#PSTip Working with DateTime objects in PowerShell using [System.DateTime] System.DateTime ParseExact