DateTimeとTimeSpanをWindows PowerShellであれこれ

書き始めた時はWindows PowerShellで時刻と時間をあれこれだったのですが、記事を書きあげてみたらWindows PowerShellがあんまり関係ない話になっていました

この記事は DateTime、TimeSpan、TimeZoneInfo、CultureInfoを知っている人には不要です


WindowsPowerShell (というか.NETで) 時間に関するデータを扱う場合、時刻 (特定の日時) ならDiteTimeを、時間 (時刻から時刻の間) ならTimeSpanはを使います

Windows PowerShell でDiteTimeのオブジェクトを作る場合、他のオブジェクト同様にNewからも作れますが、文字列や数値からの変換でも作ることが出来ます

数値を与えた場合、Ticks (1/10,000,000秒、西暦1年1月1日午前0時からの経過時間) として扱われます

PS> [DateTime]::New(2017,1,2,3,4,5)
2017年1月2日 3:04:05

PS> [DateTime]'2017/6/7 8:9:10'
2017年6月7日 8:09:10

PS> [DateTime]10000000
0001年1月1日 0:00:01

TimeSpan型も同様にNewや数値からも作れます (DateTime同様 Ticks として扱われます) が、DateTimeオブジェクト同士を減算するとTimeSpanオブジェクトが戻り値になります

ちなみに、DateTimeオブジェクトにTimeSpanオブジェクトを加算または減算するとDateTimeオブジェクトになります

PS> [TimeSpan]10000000;
Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 0
Ticks             : 10000000
TotalDays         : 1.15740740740741E-05
TotalHours        : 0.000277777777777778
TotalMinutes      : 0.0166666666666667
TotalSeconds      : 1
TotalMilliseconds : 1000

PS> [DateTime] '2017/1/1' - [TimeSpan]::New(10,0,0,0);
2016年12月22日 0:00:00

PS> [DateTime]'2017/12/1 12:0:0+05:00' - [DateTime] '2017/1/1 1:10:30-09:00';
Days              : 333
Hours             : 20
Minutes           : 49
Seconds           : 30
Milliseconds      : 0
Ticks             : 288461700000000
TotalDays         : 333.867708333333
TotalHours        : 8012.825
TotalMinutes      : 480769.5
TotalSeconds      : 28846170
TotalMilliseconds : 28846170000

Windows PowerShellでこれらを扱う場合、DateTimeオブジェクトとTimeSpanオブジェクトはそれぞれGet-Dateコマンドレット、New-TimeSpanコマンドレットでも生成できます

Get-Dateコマンドレットはパラメータなしで実行すると現在時刻が設定され、[DateTime]::Nowと同じになります

Get-Dateには.NETのStrings.Formatと同じ形式で出力される形式を指定できる-Formatパラメータ、UNIXのdateのフォーマットと同じ書式で出力される形式を指定できる-UFormatがあります

-Formatの場合、ToStringで同様の処理ができますが、-UFormatを使いたい場合、Get-Dateを使うことになります

PS> ([DateTime] '2017/12/1 15:0:0+09:00').ToString('yyyy年MM月dd日 (dddd) HH時mm分ss秒');
2017年12月01日 (金曜日) 15時00分00秒

PS> Get-Date -Date '2017/12/1 15:0:0+09:00' -Format 'yyyy年MM月dd日 (dddd) HH時mm分ss秒';
2017年12月01日 (金曜日) 15時00分00秒

PS> Get-Date -Date '2017/12/1 15:0:0+09:00' -UFormat '%Y年%m月%d (%A) %H時%M分%S秒'
2017年12月01日 (金曜日) 15時00分00秒

ここまでの例では世界標準時との時差が自動的に9時間に補正されていたり、曜日の表記が日本語になっていますが、これは実行環境に依存した値です

まず、時差を決定しているタイムゾーンの情報については [TimeZoneInfo]::Local で現在のシステムのタイムゾーンを取得できます

時差はBaseUtcOffsetプロパティから取得でき、TimeSpan型です

PS> >[TimeZoneInfo]::Local;
Id                         : Tokyo Standard Time
DisplayName                : (UTC+09:00) 大阪、札幌、東京
StandardName               : 東京 (標準時)
DaylightName               : 東京 (夏時間)
BaseUtcOffset              : 09:00:00
SupportsDaylightSavingTime : False

PS> [System.TimeZoneInfo]::Local.BaseUtcOffset.GetType().Name;
TimeSpan

タイムゾーンIDでDateTimeを別の時間帯の時刻に変換することもできます

タイムゾーンIDは[TimeZoneInfo]::GetSystemTimeZones()により全てのタイムゾーンを取得できるのでそこから調べる事ができます

また、[TimeZoneInfo]::FindSystemTimeZoneByIdを用いて、IdからTimeZoneInfoを得ることもできます

PS> [TimeZoneInfo]::ConvertTimeBySystemTimeZoneId([DateTime]'2017/12/1 15:00:00+09:00', 'Eastern Standard Time');
2017年12月1日 1:00:00

[TimeZoneInfo]::FindSystemTimeZoneById('Eastern Standard Time');
Id                         : Eastern Standard Time
DisplayName                : (UTC-05:00) 東部標準時 (米国およびカナダ)
StandardName               : 東部標準時
DaylightName               : 東部夏時間
BaseUtcOffset              : -05:00:00
SupportsDaylightSavingTime : True

一方、2017/12/1の曜日を金曜日と表示されているのは CultureInfo によるものです

上記の例で2017/12/1の曜日が金曜日と日本語で出力されていたのはが、実行した環境のCultureInfoが日本 ('ja-JP ')だからで、例えば2017/12/1の曜日を "金曜日" でなく 英語 (米国) 表記で "Friday" と得たい場合、'en-US' を設定したカルチャ情報を指定することで実現できます

PS> [CultureInfo]::CurrentCulture;
LCID             Name             DisplayName
----             ----             -----------
1041             ja-JP            日本語 (日本)

PS> [CultureInfo]::new('en-US');
LCID             Name             DisplayName
----             ----             -----------
1033             en-US            英語 (米国)

PS> ([DateTime] '2017/12/1').ToString('dddd', [CultureInfo]::new('en-US'));
Friday

カルチャ情報に結び付けられた日付の表記情報についてはDateTimeFormatプロパティを参照してみてください

そんな感じで一つ