最近ブログを書く気力が薄れてしまっているので軽いネタでリハビリします。
小ネタがいくつかたまっているので何とか消化したいですね...
New-Object System.Datetime と Get-Date の違い
先ずはこちらのコードをご覧ください。
PS C:\> $Date1 = New-Object System.Datetime @(2016, 3, 22) PS C:\> $Date2 = Get-Date -Year 2016 -Month 3 -Day 22
上のコードで取得できる$Date1
と$Date2
は同じ値になると思いますか?
$Date1
は年、月、日を指定するコンストラクタでSystem.DateTime
の値を生成します。
$Date2
はGet-Date
コマンドレットで年、月、日を指定してSystem.DateTime
の値を取得しています。
実際に比較すると結果はFalse
を返し二つの値は異なることがわかります。
PS C:\> $Date1 -eq $Date2 False
どちらも本日(2016/03/22)の値を取得していますが、もう少し詳しく見てみると、$Date1
は年月日以外は初期値なのですが、$Date2
は年月日以外に現在時刻が設定されています。
PS C:\> $Date1.ToString("yyyy/MM/dd HH:mm:ss.fff") 2016/03/22 00:00:00.000 PS C:\> $Date2.ToString("yyyy/MM/dd HH:mm:ss.fff") 2016/03/22 20:01:27.973
Get-DateはGet-DateであってNew-Dateでは無いお話し
Get-Dateの仕様について
私はずっと上記例の$Date1
と$Date2
は同じ値を返すものだと思い込んでいました。
ただ、各パラメーターのヘルプを見てみると確かに、
-Year
表示する年を指定します。1 ~ 9999 の値を入力します。既定値は現在の年です。
-Month
表示する月を指定します。1 ~ 12 の値を入力します。既定値は現在の月です。
-Day
表示されている月の日にちを指定します。1 ~ 31 の値を入力します。既定値は現在の日付です。
-Hour
表示する時を指定します。1 ~ 23 の値を入力します。既定値は現在の時です。
-Minute
表示する分を指定します。1 ~ 59 の値を入力します。既定値は現在の分です。
-Second
表示する秒を指定します。1 ~ 59 の値を入力します。既定値は現在の秒です。
-Millisecond
日付のミリ秒を指定します。0 ~ 999 の値を入力します。既定値は現在のミリ秒数です。
と既定値が「現在の○○です。」になっており、現在時刻の値を設定する様になっていました。
Get-DateはGet-DateであってNew-Dateではないお話し
私見を述べれば何故こんなわけのわからない仕様にしたのだという気持ちでいっぱいです。
PowerShellでは$Date2
の様にNew-Object
でDatetime
型の値も生成できるので上記の例が同じ値になる方が直感的であり統一性もあると思っています。
中の人たちがどの様な意図でこの仕様にしたのか断定できる資料は無いのですが、推測すると、Get-Date
の概要には、
概要
現在の日付と時刻を取得します。
とあるので、このコマンドレットはあくまでも"現在時刻を取得する"ものであり"時刻を生成するものではない"という事なのでしょう...
不満で仕方ありませんがそういうものだと割り切ることにします。
New-Dateを作ってみた
ただ、何もせずにこの仕様に従うのが悔しかったので極力Get-Date
と互換のあるNew-Date
を作ってみました。
以下の様なコードになります。
こいつを使えば上記の例も、以下の様に同じ値を返す様になります。
PS C:\> $Date1 = New-Object System.Datetime @(2016, 3, 22) PS C:\> $Date2 = New-Date -Year 2016 -Month 3 -Day 22 PS C:\> $Date1 -eq $Date2 True
実際の運用ではこのファンクションを使うことは無いとは思いますが*1参考までにという事で。
補足 もうひとつのNew-Object System.Datetime と Get-Date の違い
補足として、New-Object
を使った場合とGet-Date
を使ってSystem.Datetime
型の値を取得した場合のもう一つの違いについて説明します。
前項のNew-Date
のコード内で軽くネタバレしているのですが、Get-Date
で取得したSystem.Datetime
型の値にはDisplayHint
NotePropertyが付与されています。
最初の例の結果に対してそれぞれGet-Member
してやると、
PS C:\> $Date1 | Get-Member -View Extended TypeName: System.DateTime Name MemberType Definition ---- ---------- ---------- DateTime ScriptProperty System.Object DateTime {get=if ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq "... PS C:\> $Date2 | Get-Member -View Extended TypeName: System.DateTime Name MemberType Definition ---- ---------- ---------- DisplayHint NoteProperty DisplayHintType DisplayHint=DateTime DateTime ScriptProperty System.Object DateTime {get=if ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq...
とGet-Date
で得た方の値にのみDisplayHint
プロパティが付いている事がわかります。
このDisplayHint
プロパティはコンソールにSystem.Datetime
型の値を表示する際のフォーマットをつかさどり、既定値はDatetime
で日付と時刻がコンソールに表示されます。
このプロパティを変えるとコンソールに表示される内容が変化します。
# DisplayHintプロパティの既定値は DateTime PS C:\> $Date2.DisplayHint DateTime # 既定ではコンソールには日付と時刻が表示される PS C:\> $Date2 2016年3月22日 0:00:00 # DisplayHintの値を変えるとコンソールに表示される内容も変わる PS C:\> $Date2.DisplayHint = [Microsoft.PowerShell.Commands.DisplayHintType]::Date PS C:\> $Date2 2016年3月22日
最後に
とりとめのない感じになりましたがとりあえずこんな感じです。
Get-Date
を使う際はちょっとだけ注意してみてください。
*1:作った本人もこんなものをいちいち使う気はないですw