2024/08/25

秒数を 時:分:秒 に見やすく変換

先日、『DXL 拡張ライブラリをリリースします!』の記事の中で、ライブラリの活用事例として数字パズルゲームを紹介しました。”数独” と紹介したのですが、商標登録されているようなので、より一般的な ”ナンプレ” と訂正させていただきます。商標登録は国内だけなので海外では ”Sudoku” も一般的に使用されているようです。スマホアプリでは ”Sudoku” が多数あったのでつい使ってしまいました...


さて、9 月 19 日の DominoHub 2024 Osaka に向けて DXL 拡張ライブラリ dxlSuite for LotusScript と新生 ”dxl ナンプレ” の開発を急ピッチで進めております。本日はその作業の過程で作成したコードを紹介します。


紹介する事例

下図は、開発中の dxl ナンプレ でパズルの問題(ステージ)を選択する画面です。

パズルの右側にはハイスコア機能を作成しました。過去にクリアを時間順にランキング表示する機能なのですが、この時間、内部的には秒で管理しています。これをそのまま表示すると、318.2、374.7、1356.9 となり、わかりにくいですね。

今回はこの秒数を 時 分 秒 でわかりやすく変換するコードを紹介します。


変換の仕様は次の通りとします。

  • 秒 の表示は少数 1 桁
  • 時 分 は存在する場合のみ表示
  • 時 分 秒 の区切り文字は ”:”
  • 上の桁が存在する場合は、0 編集
  • 24 時間を越えても 日 に変換しない

例えば次のように変換します。

6.5 6.5
60.5 1:00.5 上の桁が存在する場合は、0 編集
3600.5 1:00:00.5
360000.5 100:00:00.5 24 時間を越えても 日 に変換しない


サンプルコード

今回の変換は@関数と LotusScript で作成しました。変換手順をそろえていますので、比較すると言語の違いが確認できます。

変換の処理は、秒数を 時 分 秒 のそれぞれの桁に分離してから文字列にしています。分と秒については上の桁の存在確認をして、0 編集するか決定しています。


@関数の場合

計算結果フィールドの式として作成したコードです。最初の Sec が変換する秒数を保持しているフィールドです。

xSec := Sec;
@If(xSec = ""; @Return(""); @Success);

REM "分と秒に分離";
xMin := @Integer(xSec / 60);
xSec := xSec - xMin * 60;

REM "分を時間と分に分離";
xHour := @Integer(xMin / 60);
xMin := xMin - xHour * 60;

REM "時分秒毎に文字列化";
xStrH := @If(xHour > 0; @Text(xHour) + ":"; "");
xStrM := @If(xMin > 0; @Text(xMin) + ":"; "");
xStrM := @If(xStrH = ""; xStrM; @If(xStrM = ""; "00:"; @Right("0" + xStrM; 3)));
xStrS := @Text(xSec; "F1");
xStrS := @If(xStrH+xStrM = ""; xStrS; @Right("00" + xStrS; 4));

xStrH + xStrM + xStrS


LotusScript の場合

LotusScript では関数化しています。引数に変換する秒数を与えると変換された値が戻り値で返される仕様としています。

Function xSec2Str(Byval vdSec As Double) As String
  Dim dSec As Double
  Dim lMin As Long
  Dim lHour As Long
  Dim sStrS As String
  Dim sStrM As String
  Dim sStrH As String

  '分と秒に分離
  lMin = Int(vdSec / 60)
  dSec = vdSec - lMin * 60

  '分を時間と分に分離
  lHour = Int(lMin / 60)
  lMin = lMin - (lHour * 60)

  '時分秒毎に文字列化
  If lHour > 0 Then sStrH = Cstr(lHour) & ":"
  If lMin > 0 Then sStrM = Cstr(lMin) & ":"
  If sStrH <> "" Then
    If sStrM = "" Then
      sStrM = "00:"
    Else
      sStrM = Right("0" & sStrM, 3)
    End If
  End If
  sStrS = Format(dSec, "0.0")
  If sStrH & sStrM <> "" Then
    sStrS = Right("0" & sStrS, 4)
  End If

  xSec2Str = sStrH & sStrM & sStrS
End Function

細かな点ではありますが、時 分 を管理する変数を Long 型にしてオバーフローさせないようにしています。

0 件のコメント:

コメントを投稿