Windows10の日付表示カスタマイズとその影響範囲の微妙さについて

# ３行でまとめると
* Windows10 の日付表示には微妙なカスタマイズが可能です。
* しかしそのカスタマイズによってVBAへの意外な副作用を踏み抜いてハマりました。
* 教訓として、あまり知られていないマイナーなカスタマイズはやめておいた方が無難です。
* とはいえ、その仕様ってどうよ…？

という話になります。4行ですが。

# 日付表示のカスタマイズ
* あまり知られていないのですが、Windowsのエクスプローラの日付表示に曜日を表示させることが可能です。

* こんな感じです↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/e8995817-42fa-a600-6c48-7c8206832888.png)

* 何気に date コマンドの出力も変わります。
* 普通はこうなのですが…↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/0579c058-e976-2afd-2462-a7546c6cfd50.png)
* こう変わります↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/8c64ea1b-c84b-1bd4-08cc-123b6882d85f.png)

# 設定方法
1. コントロールパネルで「地域」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/1b36e687-6908-5c98-7864-756047c07b19.png)

2. このようなダイアログが出ます。ここに表示されている「日付（短い形式）」をカスタマイズします。下の方にある「追加の設定(D)…」を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/85e393bd-b64e-1bac-5ce9-2d8d0cb2c022.png)

3. すると「形式のカスタマイズ」というダイアログが出ます。このダイアログの「日付」タブの真ん中あたりに短い形式(S):という項目があります。デフォルトでは「yyyy/MM/dd」と入っていると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/b8bd428c-7d34-e18d-09bb-4fef23512b61.png)

4. このフォーマットに追記して「yyyy/MM/dd ddd」とし、OKか適用ボタンを押して戻ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/bb370d9d-b7bb-12d9-24fa-820d282b3eb8.png)

5. すると最初に見せたような形にエクスプローラーの日付の表示が変わっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/e8995817-42fa-a600-6c48-7c8206832888.png)
 
6. しかも実は、「ddd」だと「月」とか「火」となりますが、「dddd」だと「月曜日」とか「火曜日」という風に長い表示になります。細かいです。この機能需要あるんでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/5703179d-924d-9ea7-30f9-0bd1338a0e22.png)

* 不思議なことに、dateコマンドの出力は「dddd」にしても「水曜日」とはならず、「ddd」の時と同じで「水」のままでした。中途半端です。やるなら最後まで貫いて欲しい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/89e124a6-d585-bf9a-62bd-70c600e0a5df.png)

* 余談ですが、Windows10だとエクスプローラーの詳細表示が変わるだけですが、Windows11で同様の設定をするとタスクバーの日付表示の横に曜日が表示されます。細かいです。需要あるんでしょうか。こちらはあるかな。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/0455fd24-e833-0d54-76b1-8b2d4a86df93.png)

# 話はそれだけでは終わらなかった。
* これだけだったら単なるマイナーなカスタマイズ機能ですほう、で終わりなのですが…そうは問屋が卸しませんでした。
* カスタマイズの話とはまったく関係なく、とあるExcel VBAで作られたマクロがありました。これをとある事情により使っていたのですが、上記日付表示のカスタマイズを行ってからしばらくしてこのExcelマクロを動かした所、まともに動かなくなっていることが判明しました。データも何も変わっていないのに突然動かなくなったのでびっくりして原因を調べたところ、このような処理をしている箇所があることに気づきました。勝手に転載すると怒られるかもなので、下記は問題点を示すための疑似的なコードです。

``` vb:
    Dim s as String
    s = Cells(x, y).Value 'ここには日付値が入っている
    If IsDate(s) = True Then
       ' 肝心な処理
       '...
    End If    
```
* この「肝心な処理」の所を通っていないのが原因らしい…
* この文字列 s は、普通なら yyyy/mm/dd の形式となるはずなのですが…まさかと思い、こういうシートを作成し…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261111/f5c9ca74-1066-890f-2a8a-faf35a5e8c7e.png)　
以下のようなコードを書いてみました。
``` vb:
    Dim w As Worksheet
    Set w = ActiveSheet
    
    Dim s As String
    s = w.Range("C5").Value 
    Debug.Print ("s=" & s)
    Debug.Print ("IsDate(s)の判定結果=" & IsDate(s))
```
``` : 実行結果
s=2022/07/19 火
IsDate(s)の判定結果=False
```
なんですかそれは… Windowsの日付表示設定がExcelの日付値の文字列変換の動作に影響しているのか？
その謎を解明するため、日付表示の設定を元に戻してみて、再度実行してみました。
``` : 実行結果
s=2022/07/19
IsDate(s)の判定結果=True
```
直りました[^1]。まじですかい…本当に影響してました。それなら、「yyyy/MM/dd dddd」にしたら「2022/07/19 火曜日」になるのかい？
``` : 実行結果
s=2022/07/19 火曜日
IsDate(s)の判定結果=False
```
見事になっています。

## セルの日付値を取り出してStringに変換するのがいけないのか？
* ならば DateとかVariant で受けたらどうなる？ということで、やってみました。
``` vb:
    'Stringで受けた場合
    Dim s As String
    s = w.Range("C5").Value
    Debug.Print ("s=" & s)
    Debug.Print ("IsDate(s)の判定結果=" & IsDate(s))
    
    'Dateで受けた場合
    Dim d As Date
    d = w.Range("C5").Value
    Debug.Print ("d=" & d)
    Debug.Print ("IsDate(d)の判定結果=" & IsDate(d))
    
    'Variantで受けた場合
    Dim v As Variant
    v = w.Range("C5").Value
    Debug.Print ("v=" & v)
    Debug.Print ("IsDate(v)の判定結果=" & IsDate(v))
```
``` : 実行結果
s=2022/07/19 火曜日
IsDate(s)の判定結果=False
d=2022/07/19 火曜日
IsDate(d)の判定結果=True
v=2022/07/19 火曜日
IsDate(v)の判定結果=True
```
Date型やVariant型であれば表示は「火曜日」だけどIsDate()判定は正しい結果になる。そうなんだ…へぇ……


# まとめ
## 【教訓】Excel VBAで日付値を取り出すときに安易に String で受けてはいけません。
* ということですね… Stringで受けるということは、値を「文字列表現」に変えたということ。単なる表現に過ぎない文字列は、本質的な値ではなく、OS側の設定によって変わってしまうので処理を制御するための判別値に使ってはいかん、と言うわけです。制御に使いたいならDateとかVariantで受けなさいと、いうことらしいです。なるほど勉強になりました。


## 【根本的教訓】みんながしないようなマイナーなカスタマイズをすると痛い目に合うのでやめておいた方が無難
* ということですよね。だけどそれをやってみたくなるのが人というものなんじゃないですか…


## 【問題提起】しかしそれなら IsDate(文字列)の存在意義ってなんです？[^2]
* 冷静に考えて見ると、そもそもですが、OSの表示カスタマイズ設定がExcelの動作に影響するってありなの？
* 百歩譲ってありだとして、OS側で日付文字列のフォーマットの設定が変わったときにVBA側の日付→文字列の変換ロジックが変わるのならば、IsDate()の判定ロジックも一緒に合わせて変わってくれてもいいんじゃないでしょうか？仕様の一貫性的な意味で、おかしくないです？


* などと無駄な一石を投じつつ、今回の記事は以上です。最後までお読みいただきありがとうございました。

# 【参考情報】今回動作確認した環境
・Windows10 Pro Version. 21H2 OSビルド 19044.1826
・Microsoft Office Personal 2019
・Microsoft® Excel® 2019 MSO (バージョン 2206 ビルド 16.0.15330.20260) 32 ビット 

[^1]: Excelマクロの誤動作もこの時点で修復していました。

[^2]: IsDate()の引数は正式にはVariant型らしいです。