以前、Get-Dateコマンドレットで出力される標準書式について記事を書きました。
PowerShellのGet-Date -Formatで出力される標準の書式指定結果一覧
今回は、PowerShellでDateTime型にキャストする際、PowerShellでのカスタム書式指定についてみていきます。
日付を取得する
繰り返しになりますが、PowerShellで日付を取得する方法をみてみます。
コマンドレットで日付を取得する
何も指定しなければ、本日が取得できます。
PS> Get-Date 2013年2月9日 10:36:09
結果に対して、.AddDaysや.AddMonthsなどで対象プロパティを操作もできます。 例えば取得結果から、一日進めるならこうです。
PS> (Get-Date).AddDays(1) 2013年2月10日 10:39:13
.NETで日付を取得する
これで本日が取得できます。
PS> [System.DateTime]::Now 2013年2月9日 10:41:52
[System.DateTime]は[DateTime]に短縮できます。 日付のみを取得するなら、Todayメソッドを利用してかけます。
PS> [DateTime]::Today 2013年2月9日 0:00:00
文字列を日付型にキャストする
文字列から日付型へのキャスト(型変換)をみてみます。
暗黙の型変換
1つは、「DateTimeにしなさい」と指定する方法です。 この場合は、PowerShellがDateTime型に変換するため理解できる書式である必要があります。 例えばこうです。
PS> [DateTime]"2013/02/09" 2013年2月9日 0:00:00 PS> [DateTime]"2013/02/09 13:59:50" 2013年2月9日 13: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") 2013年2月9日 0:00:00 PS> [Datetime]::Parse("2013/02/09 13:59:50") 2013年2月9日 13: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) 2012年11月12日 13: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) 2013年2月9日 0:00:00
[DateTime]::ParseExact利用時の注意
問題があるようなので注意しましょう。
DateTime.ParseExactメソッドで、1900年代の日時に変換される
PS> [DateTime]::ParseExact("301112 13:59:51","yyMMdd HH:mm:ss",[System.Globalization.CultureInfo]::InvariantCulture) 1930年11月12日 13: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) 2012年11月12日 13:59:51
基本的にPowerShellにおいては、$nullか[System.Globalization.CultureInfo]::InvariantCulture)を指定しておくことで、現在のスケールで出力されます。
まとめ
PowerShellでのカスタム日付指定は、単純なパターンであれば[DateTime]で型変換して.ToString()メソッドで指定にて問題ないでしょう。ただ、[DateTime]::ParseExact()を利用することで、柔軟な読み取りパターン指定ができます。
次回は、[DateTime]::ParseExact()にて国(Culture)を指定する方法を紹介します。