Format関数で12時間表記の時刻を取得する


VB .Netでプログラムを作っていて、ちょっと悩んでしまいました。タイマーコントロールを使って、ラベルに現在の時刻を表示していたんです。特に難しくありませんね。

 Label1.Text = Format(Now(), "hh:mm:ss")

みたいな感じです。あ、ちなみにVB .Netでは、CaptionプロパティではなくTextプロパティです。これで確かに現在の時刻が表示されていたのですが、しばらくしてフト見ると違和感が・・・時刻が午後になったら、12時間表記で表示されているんです。

へぇ、Format関数の仕様が変わったんだ。ってことで、調べてみたら

 Label1.Text = Format(Now(), "HH:mm:ss")

と大文字で指定すると24時間表記になるんだそうです。なるほどね、VBAのFormat関数はいつも時刻を24時間表記で返してくれるもんな。やっぱVBAは便利だな・・・ん?待てよ。じゃ、VBAのFormat関数で時刻を12時間表記したいときは、どうしたらいいんだろう。今まで考えたことがなかったです。

Format関数は、セルの表示形式で指定できるのとほぼ同じ書式記号を使えます。ただし、そのほかにも、Format関数独自の機能なんかもあったりします。詳しくは、下記のページをご覧ください。

Format関数と表示形式の違い

上記のページで解説している「Medium Time」を使うと、12時間表記の時刻を指定できるようです。やってみましょう。

Sub Sample1()
    MsgBox Format(Time, "hh:mm:ss") & vbCrLf & _
    Format(Time, "Medium Time")
End Sub

比較のために、普通にhh:mm:ssを指定したFormat関数も使ってみました。「Medium Time」で返る結果は、Windowsのコントロールパネルで定義されています。Excelだけの問題ではありません。もちろん、コントロールパネルを変更すれば「午前/午後」などの表記を変更することもできるでしょうけど、Excel以外の、他のアプリケーションも影響されますので、あまり変えたくありません。

コントロールパネルの設定をこのまま使うとして、どうしても「Medium Time」を使うのでしたら、午前/午後表記を取り除いて、後ろに秒をくっつける手でしょうか。

Sub Sample2()
    MsgBox Split(Format(Time, "Medium Time"), " ")(0) & ":" & Format(Time, "ss")
End Sub

なんか、面倒くさいですね。あ、もちろん、現在の時刻が12時を過ぎているかどうかを判定して、午後だったら12時間を引いてやる手もあります。

Sub Sample3()
    If Hour(Time) > 12 Then
        MsgBox Format(Time - TimeValue("12:0:0"), "hh:mm:ss")
    Else
        MsgBox Format(Time, "hh:mm:ss")
    End If
End Sub

こうすればできるのは当たり前ですが、なんかシャクですから、これは最後の手段に取っておきましょう。ちなみに「12時間を引く」というようなとき、シリアル値の仕組みから

え~と・・・1日が1なんだから、1時間は1/24だろ
12時間ってことは、1/24を12倍するわけだから・・・
だけど1/24は割り切れないし・・・え~と

などと、シリアル値を数値として処理しようとする人がいますが、VBAにはもっと便利な機能があるんですよ。TimeValue関数は、文字列で指定した時間を表すシリアル値を返します。「Time - 0.0416666 * 12」だとか「Time - (1 / 2)」なんて書くよりも、はるかにスマートですし、何より可読性に優れていますね。

セルの表示形式で使える書式記号を見ていたら「時刻を12時間表記する記号」というのを見つけました。はいはい、そういえばありましたね、こんなのが。hh:mm:ssの後ろにAM/PMを付けるんです。実行すると次のようになります。

Sub Sample4()
    MsgBox Format(Time, "hh:mm:ss AM/PM")
End Sub

ちなみに、セルの表示形式では、次のように地域を区別するロケールを指定できますが、VBAからは使えないようです。

Sub Sample5() 'VBAでは無視される
    MsgBox Format(Time, "[$-411]hh:mm:ss AM/PM")
End Sub

AM/PMを付けると、確かに12時間表記になりました。しかも、Medium Timeなんかと違って、ちゃんと秒まで表示されています。ただ、最後のPMが邪魔ですね。これでは、午前の時刻にもAMが付いてしまいます。そこで、さっきやったSplit関数で、後ろのAM/PMを除去しましょう。

Sub Sample6()
    MsgBox Split(Format(Time, "hh:mm:ss AM/PM"), " ")(0)
End Sub

これが、一番シンプルですかね。