前回、
[DateTime]::ParseExact
メソッドを利用したカスタム日付書式について紹介しました。
PowerShellで日付書式にカスタム書式パターンを指定する
今回は、CultureInfoを指定してみます。
現在のCultureInfoを取得する
まずはCultureInfoクラスから確認します。
MSDN - CultureInfo Class
どうやらCurrentCultureプロパティから取得できますね。
以下のコードで取得できます。
[System.Globalization.CultureInfo]::CurrentCulture
現在のThreadで取得しましょう。
$currentThread = [System.Threading.Thread]::CurrentThread
$currentThread.CurrentCulture
取得結果です。
LCID Name DisplayName
---- ---- -----------
1041 ja-JP 日本語 (日本)
CultureInfoの一覧を取得する
何はともあれ、指定できるCultureInfoの一覧が知りたいですね。
必要な情報は、
CultureInfo.CreateSpecificCulture
で取得できそうです。
MSDN - CultureInfo.CreateSpecificCulture Method
PowerShellでは、このコードでSpecificCulturesのコード一覧を取得できます。
[System.Globalization.Cultureinfo]::getcultures([System.Globalization.CultureTypes]::SpecificCultures)
取得した一覧です。
LCID Name DisplayName
---- ---- -----------
1025 ar-SA アラビア語 (サウジアラビア)
1026 bg-BG ブルガリア語 (ブルガリア)
1027 ca-ES カタルニア語 (カタルニア)
1028 zh-TW 中国語 (繁体字、台湾)
1029 cs-CZ チェコ語 (チェコ共和国)
1030 da-DK デンマーク語 (デンマーク)
1031 de-DE ドイツ語 (ドイツ)
1032 el-GR ギリシャ語 (ギリシャ)
1033 en-US 英語 (米国)
1035 fi-FI フィンランド語 (フィンランド)
1036 fr-FR フランス語 (フランス)
1037 he-IL ヘブライ語 (イスラエル)
1038 hu-HU ハンガリー語 (ハンガリー)
1039 is-IS アイスランド語 (アイスランド)
1040 it-IT イタリア語 (イタリア)
1041 ja-JP 日本語 (日本)
1042 ko-KR 韓国語 (韓国)
1043 nl-NL オランダ語 (オランダ)
1044 nb-NO ノルウェー語 ブークモール (ノルウェー)
1045 pl-PL ポーランド語 (ポーランド)
1046 pt-BR ポルトガル語 (ブラジル)
1047 rm-CH ロマンシュ語 (スイス)
1048 ro-RO ルーマニア語 (ルーマニア)
1049 ru-RU ロシア語 (ロシア)
1050 hr-HR クロアチア語 (クロアチア)
1051 sk-SK スロバキア語 (スロバキア)
1052 sq-AL アルバニア語 (アルバニア)
1053 sv-SE スウェーデン語 (スウェーデン)
1054 th-TH タイ語 (タイ)
1055 tr-TR トルコ語 (トルコ)
1056 ur-PK ウルドゥー語 (パキスタン・イスラム共和国)
1057 id-ID インドネシア語 (インドネシア)
1058 uk-UA ウクライナ語 (ウクライナ)
1059 be-BY ベラルーシ語 (ベラルーシ)
1060 sl-SI スロベニア語 (スロベニア)
1061 et-EE エストニア語 (エストニア)
1062 lv-LV ラトビア語 (ラトビア)
1063 lt-LT リトアニア語 (リトアニア)
1064 tg-Cyrl-TJ タジク語 (キリル、タジキスタン)
1065 fa-IR ペルシャ語
1066 vi-VN ベトナム語 (ベトナム)
1067 hy-AM アルメニア語 (アルメニア)
1068 az-Latn-AZ アゼルバイジャン語 (ラテン、アゼルバイジャン)
1069 eu-ES バスク語 (バスク)
1070 hsb-DE 上ソルブ語 (ドイツ)
1071 mk-MK マケドニア語 (マケドニア旧ユーゴスラビア共和国)
1074 tn-ZA セツワナ語 (南アフリカ)
1076 xh-ZA コサ語 (南アフリカ)
1077 zu-ZA ズールー語 (南アフリカ)
1078 af-ZA アフリカーンス語 (南アフリカ)
1079 ka-GE グルジア語 (グルジア)
1080 fo-FO フェロー語 (フェロー諸島)
1081 hi-IN ヒンディー語 (インド)
1082 mt-MT マルタ語 (マルタ)
1083 se-NO 北サーミ語 (ノルウェー)
1086 ms-MY マレー語 (マレーシア)
1087 kk-KZ カザーフ語 (カザフスタン)
1088 ky-KG キルギス語 (キルギス)
1089 sw-KE スワヒリ語 (ケニア)
1090 tk-TM トルクメン語 (トルクメニスタン)
1091 uz-Latn-UZ ウズベク語 (ラテン、ウズベキスタン)
1092 tt-RU タタール語 (ロシア)
1093 bn-IN ベンガル語 (インド)
1094 pa-IN パンジャーブ語 (インド)
1095 gu-IN グジャラート語 (インド)
1096 or-IN オリヤー語 (インド)
1097 ta-IN タミール語 (インド)
1098 te-IN テルグ語 (インド)
1099 kn-IN カナラ語 (インド)
1100 ml-IN マラヤラム語 (インド)
1101 as-IN アッサム語 (インド)
1102 mr-IN マラーティー語 (インド)
1103 sa-IN サンスクリット語 (インド)
1104 mn-MN モンゴル語 (キリル、モンゴル)
1105 bo-CN チベット語 (中国)
1106 cy-GB ウェールズ語 (英国)
1107 km-KH クメール語 (カンボジア)
1108 lo-LA ラオス語 (ラオス人民民主共和国)
1110 gl-ES ガリシア語 (ガリシア)
1111 kok-IN コンカニ語 (インド)
1114 syr-SY シリア語 (シリア)
1115 si-LK シンハラ語 (スリランカ)
1116 chr-Cher-US チェロキー語 (チェロキー)
1117 iu-Cans-CA イヌクティトット語 (カナダ音節文字、カナダ)
1118 am-ET アムハラ語 (エチオピア)
1121 ne-NP ネパール語 (ネパール)
1122 fy-NL フリジア語 (オランダ)
1123 ps-AF パシュトゥー語 (アフガニスタン)
1124 fil-PH フィリピノ語 (フィリピン)
1125 dv-MV ディヘビ語 (モルディブ)
1128 ha-Latn-NG ハウサ語 (ラテン、ナイジェリア)
1130 yo-NG ヨルバ語 (ナイジェリア)
1131 quz-BO ケチュア語 (ボリビア)
1132 nso-ZA セソト サ レボア語 (南アフリカ)
1133 ba-RU バシュキール語 (ロシア)
1134 lb-LU ルクセングルグ語 (ルクセンブルグ)
1135 kl-GL グリーンランド語 (グリーンランド)
1136 ig-NG イボ語 (ナイジェリア)
1139 ti-ET ティグリニア語 (エチオピア)
1141 haw-US ハワイ語 (米国)
1144 ii-CN イ語 (中国)
1146 arn-CL マプドゥングン語 (チリ)
1148 moh-CA モホーク語 (モホーク)
1150 br-FR ブルトン語 (フランス)
1152 ug-CN ウイグル語 (中国)
1153 mi-NZ マオリ語 (ニュージーランド)
1154 oc-FR オクシタン語 (フランス)
1155 co-FR コルシカ語 (フランス)
1156 gsw-FR アルザス語 (フランス)
1157 sah-RU サハ語 (ロシア)
1158 qut-GT キチェ語 (グアテマラ)
1159 rw-RW キニヤルワンダ語 (ルワンダ)
1160 wo-SN ウォロフ語 (セネガル)
1164 prs-AF ダリー語 (アフガニスタン)
1169 gd-GB スコットランド ゲール語 (英国)
1170 ku-Arab-IQ 中央クルド語 (イラク)
2049 ar-IQ アラビア語 (イラク)
2051 ca-ES-valencia バレンシア語 (スペイン)
2052 zh-CN 中国語 (簡体字、中国)
2055 de-CH ドイツ語 (スイス)
2057 en-GB 英語 (英国)
2058 es-MX スペイン語 (メキシコ)
2060 fr-BE フランス語 (ベルギー)
2064 it-CH イタリア語 (スイス)
2067 nl-BE オランダ語 (ベルギー)
2068 nn-NO ノルウェー語 ニーノシク (ノルウェー)
2070 pt-PT ポルトガル語 (ポルトガル)
2074 sr-Latn-CS セルビア語 (ラテン、セルビアおよびモンテネグロ (旧))
2077 sv-FI スウェーデン語 (フィンランド)
2092 az-Cyrl-AZ アゼルバイジャン語 (キリル、アゼルバイジャン)
2094 dsb-DE 下ソルブ語 (ドイツ)
2098 tn-BW セツワナ語 (ボツワナ)
2107 se-SE 北サーミ語 (スウェーデン)
2108 ga-IE アイルランド語 (アイルランド)
2110 ms-BN マレー語 (ブルネイ・ダルサラーム国)
2115 uz-Cyrl-UZ ウズベク語 (キリル、ウズベキスタン)
2117 bn-BD ベンガル語 (バングラデシュ)
2118 pa-Arab-PK パンジャブ語 (パキスタン・イスラム共和国)
2121 ta-LK タミール語 (スリランカ)
2128 mn-Mong-CN モンゴル語 (伝統的モンゴル文字、中国)
2137 sd-Arab-PK シンド語 (パキスタン・イスラム共和国)
2141 iu-Latn-CA イヌクティトット語 (ラテン、カナダ)
2143 tzm-Latn-DZ タマジット語 (ラテン、アルジェリア)
2151 ff-Latn-SN フラニ語 (ラテン、セネガル)
2155 quz-EC ケチュア語 (エクアドル)
2163 ti-ER ティグリニア語 (エリトリア)
3073 ar-EG アラビア語 (エジプト)
3076 zh-HK 中国語 (繁体字、香港)
3079 de-AT ドイツ語 (オーストリア)
3081 en-AU 英語 (オーストラリア)
3082 es-ES スペイン語 (スペイン)
3084 fr-CA フランス語 (カナダ)
3098 sr-Cyrl-CS セルビア語 (キリル、セルビアおよびモンテネグロ (旧))
3131 se-FI 北サーミ語 (フィンランド)
3179 quz-PE ケチュア語 (ペルー)
4097 ar-LY アラビア語 (リビア)
4100 zh-SG 中国語 (簡体字、シンガポール)
4103 de-LU ドイツ語 (ルクセンブルグ)
4105 en-CA 英語 (カナダ)
4106 es-GT スペイン語 (グアテマラ)
4108 fr-CH フランス語 (スイス)
4122 hr-BA クロアチア語 (ラテン、ボスニア ヘルツェゴビナ)
4155 smj-NO ルレ サーミ語 (ノルウェー)
4191 tzm-Tfng-MA 中央アトラス タマジット語 (ティフィナグ、モロッコ)
5121 ar-DZ アラビア語 (アルジェリア)
5124 zh-MO 中国語 (繁体字、マカオ)
5127 de-LI ドイツ語 (リヒテンシュタイン)
5129 en-NZ 英語 (ニュージーランド)
5130 es-CR スペイン語 (コスタリカ)
5132 fr-LU フランス語 (ルクセンブルグ)
5146 bs-Latn-BA ボスニア語 (ラテン、ボスニア ヘルツェゴビナ)
5179 smj-SE ルレ サーミ語 (スウェーデン)
6145 ar-MA アラビア語 (モロッコ)
6153 en-IE 英語 (アイルランド)
6154 es-PA スペイン語 (パナマ)
6156 fr-MC フランス語 (モナコ)
6170 sr-Latn-BA セルビア語 (ラテン、ボスニア ヘルツェゴビナ)
6203 sma-NO 南サーミ語 (ノルウェー)
7169 ar-TN アラビア語 (チュニジア)
7177 en-ZA 英語 (南アフリカ)
7178 es-DO スペイン語 (ドミニカ共和国)
7194 sr-Cyrl-BA セルビア語 (キリル、ボスニア ヘルツェゴビナ)
7227 sma-SE 南サーミ語 (スウェーデン)
8193 ar-OM アラビア語 (オマーン)
8201 en-JM 英語 (ジャマイカ)
8202 es-VE スペイン語 (ベネズエラ ボリバル共和国)
8218 bs-Cyrl-BA ボスニア語 (キリル、ボスニア ヘルツェゴビナ)
8251 sms-FI スコルト サーミ語 (フィンランド)
9217 ar-YE アラビア語 (イエメン)
9225 en-029 英語 (カリブ)
9226 es-CO スペイン語 (コロンビア)
9242 sr-Latn-RS セルビア語 (ラテン、セルビア)
9275 smn-FI イナリ サーミ語 (フィンランド)
10241 ar-SY アラビア語 (シリア)
10249 en-BZ 英語 (ベリーズ)
10250 es-PE スペイン語 (ペルー)
10266 sr-Cyrl-RS セルビア語 (キリル、セルビア)
11265 ar-JO アラビア語 (ヨルダン)
11273 en-TT 英語 (トリニダード・トバゴ)
11274 es-AR スペイン語 (アルゼンチン)
11290 sr-Latn-ME セルビア語 (ラテン、モンテネグロ)
12289 ar-LB アラビア語 (レバノン)
12297 en-ZW 英語 (ジンバブエ)
12298 es-EC スペイン語 (エクアドル)
12314 sr-Cyrl-ME セルビア語 (キリル、モンテネグロ)
13313 ar-KW アラビア語 (クウェート)
13321 en-PH 英語 (フィリピン共和国)
13322 es-CL スペイン語 (チリ)
14337 ar-AE アラビア語 (アラブ首長国連邦)
14346 es-UY スペイン語 (ウルグアイ)
15361 ar-BH アラビア語 (バーレーン)
15370 es-PY スペイン語 (パラグアイ)
16385 ar-QA アラビア語 (カタール)
16393 en-IN 英語 (インド)
16394 es-BO スペイン語 (ボリビア)
17417 en-MY 英語 (マレーシア)
17418 es-SV スペイン語 (エルサルバドル)
18441 en-SG 英語 (シンガポール)
18442 es-HN スペイン語 (ホンジュラス)
19466 es-NI スペイン語 (ニカラグア)
20490 es-PR スペイン語 (プエルトリコ)
21514 es-US スペイン語 (米国)
ThreadのCultrueInfoを指定する
まず、先ほど取得したコードをCultureInfoに指定します。
例えば、USを指定するならこうです。
[System.Globalization.CultureInfo]::CreateSpecificCulture("en-US")
あとは、現在のThreadに指定するだけですね。
現ThreadのCultureは、
CurrentCulture
と
CurrentUICulture
プロパティです。
このコードで指定します。
$currentThread = [System.Threading.Thread]::CurrentThread
$culture = [System.Globalization.CultureInfo]::CreateSpecificCulture("en-US")
$currentThread.CurrentCulture = $culture
$currentThread.CurrentUICulture = $culture
さあ、出力してみましょう。
$currentThread = [System.Threading.Thread]::CurrentThread
$culture = [System.Globalization.CultureInfo]::CreateSpecificCulture("en-US")
$currentThread.CurrentCulture = $culture
$currentThread.CurrentUICulture = $culture
[DateTime]::ParseExact("20121112","yyyyMMdd",[System.Globalization.CultureInfo]::CurrentCulture)
[DateTime]::ParseExact("20121112","yyyyMMdd",[System.Globalization.CultureInfo]::InvariantCulture)
[DateTime]::ParseExact("20121112","yyyyMMdd",$null)
出力結果です。
Monday, November 12, 2012 12:00:00 AM
Monday, November 12, 2012 12:00:00 AM
Monday, November 12, 2012 12:00:00 AM
勿論日本語(ja-JP)を指定しなおせば、日本語書式になります。
$currentThread = [System.Threading.Thread]::CurrentThread
$culture = [System.Globalization.CultureInfo]::CreateSpecificCulture("en-US")
$currentThread.CurrentCulture = $culture
$currentThread.CurrentUICulture = $culture
[DateTime]::ParseExact("20121112","yyyyMMdd",[System.Globalization.CultureInfo]::CurrentCulture)
[DateTime]::ParseExact("20121112","yyyyMMdd",[System.Globalization.CultureInfo]::InvariantCulture)
[DateTime]::ParseExact("20121112","yyyyMMdd",$null)
$newCulture = [System.Globalization.CultureInfo]::CreateSpecificCulture("ja-JP")
$currentThread.CurrentCulture = $newCulture
$currentThread.CurrentUICulture = $newCulture
[DateTime]::ParseExact("20121112","yyyyMMdd",[System.Globalization.CultureInfo]::CurrentCulture)
[DateTime]::ParseExact("20121112","yyyyMMdd",[System.Globalization.CultureInfo]::InvariantCulture)
[DateTime]::ParseExact("20121112","yyyyMMdd",$null)
結果です。
Monday, November 12, 2012 12:00:00 AM
Monday, November 12, 2012 12:00:00 AM
Monday, November 12, 2012 12:00:00 AM
2012年11月12日 0:00:00
2012年11月12日 0:00:00
2012年11月12日 0:00:00
読み取り文字列のCultrueInfoを指定する
この応用で、読み取りたい書式のCultureInfoが現在のCultrureInfoと異なっていても読み取らせることが可能です。
例えば、現在がja-JPの時に、MMMにNovが指定されても通常は読めません。
[System.Threading.Thread]::CurrentThread.CurrentCulture.Name
[DateTime]::ParseExact("12/Nov/2012 13:59:51","dd/MMM/yyyy HH:mm:ss",$null)
当然例外が出ます。
ja-JP
"3" 個の引数を指定して "ParseExact" を呼び出し中に例外が発生しました: "文字列は有効な DateTime ではありませんでした。"
発生場所 C:\Users\acquire\AppData\Local\Temp\fd6f6e29-713f-486c-82cb-e3b7f1d513b9.ps1:9 文字:1
+ [DateTime]::ParseExact("12/Nov/2012 13:59:51","dd/MMM/yyyy HH:mm:ss",$null)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FormatException
そこで、読み取り時のCultureInfoにen-USを指定すれば読み取り可能です。
[System.Threading.Thread]::CurrentThread.CurrentCulture.Name
[DateTime]::ParseExact("12/Nov/2012 13:59:51","dd/MMM/yyyy HH:mm:ss",[System.Globalization.CultureInfo]::CreateSpecificCulture("en-US"))
読めましたね。
ja-JP
2012年11月12日 13:59:51
読み取り日付書式をパターンとしておく
これまでの知識を利用すると、このようなことが可能になります。
Parsing Custom Date and Time Formats
これを、日本語ロケールのPCで実行しても、CultureInfoが異なるためにエラーが出ますが、en-USを指定することで実行できます。
$information = '12Nov(2012)18h30m17s'
$pattern = 'ddMMM\(yyyy\)HH\hmm\mss\s'
[datetime]::ParseExact($information, $pattern, [System.Globalization.CultureInfo]::CreateSpecificCulture("en-US"))
読み取れました。
2012年11月12日 18:30:17
これの素晴らしい所は、カスタム書式をパターンとして変数に保持して読み取りに一貫性を持たせられることを示唆していることです。
カスタム書式は、[datetime]::ParseExact()を利用することが適した場面はたくさん見かけるので活用できるといいかと思います。
もちろん、元々の書式がja-JPのCultureInfoで読めるパターンならCultureInfoの指定は不要です。
$information = '1211(2012)18h30m17s'
$pattern = 'ddMMM\(yyyy\)HH\hmm\mss\s'
[datetime]::ParseExact($information, $pattern, $null)
読み取れますね。
2012年11月12日 18:30:17
事前に、CurrentCultureをその国のCultureInfoに変更すると出力も変わります。
$currentThread = [System.Threading.Thread]::CurrentThread
$culture = [System.Globalization.CultureInfo]::CreateSpecificCulture("en-US")
$currentThread.CurrentCulture = $culture
$currentThread.CurrentUICulture = $culture
$information = '12Nov(2012)18h30m17s'
$pattern = 'ddMMM\(yyyy\)HH\hmm\mss\s'
[datetime]::ParseExact($information, $pattern, $null)
en-USの書式に変わっていますね。
Monday, November 12, 2012 6:30:17 PM
まとめ
これで、各国の日付書式にも対応させる方法が分かりました。
CurrentCultureを変える場面は少なく、.ToString()で書式を変える方が多いかとは思います。
が、読み取り時に柔軟に対応できることを覚えておくと、海外製品のログ分析などで有用になります。(経験談)
活用していただけると嬉しい限りです。
参考サイト
Random Holiday destinations in Powershell
PowerShell Scripts Blog - Show-Formatting1.ps1
How to set culture in PowerShell?