JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptで不正な時間文字列(HH:MM:SS)を正規化して修正する方法

JavaScriptでは、「HH:MM:SS」形式の時間文字列を扱う場面がよくあります。しかし、時間の加算処理などで計算ミスが発生すると、分や秒が60を超えてしまう「壊れた」時間文字列が生成されることがあります。この記事では、そうした不正な時間文字列を正しく正規化する方法を解説します。

課題:壊れた時間文字列とは

今回求められるのは、JavaScriptで「HH:MM:SS」形式の時間文字列を受け取り、必要な修正を加えた上で、正しい時間文字列として返す関数を作成することです。

問題になるのは、加算処理のバグによって、次のような不正な値が含まれてしまうケースです。

  • MM(分)の部分が60を超えている
  • SS(秒)の部分が60を超えている

たとえば、秒が71になっている次のような文字列が該当します。

"08:11:71" → "08:12:11"

この例では、秒が60を超えているため、1分繰り上げて「08時12分11秒」という正しい表現に変換する必要があります。

実装コード例

以下が実際のコード例です。全体の秒数に変換してから、各単位に再計算するというシンプルなアプローチを採用しています。

const str = '08:11:71';

const rectifyTime = (str = '') => {
  // 空文字列の場合はそのまま返す
  if (!Boolean(str)) {
    return str;
  }

  // 「HH:MM:SS」形式かどうかを正規表現で検証
  const re = /^(\d\d):(\d\d):(\d\d)$/;
  if (!re.test(str)) {
    return null;
  }

  // 時・分・秒を数値として抽出
  let [h, m, s] = str.match(re).slice(1, 4).map(Number);

  // 合計秒数に変換
  let time = h * 3600 + m * 60 + s;

  // 各単位に再計算
  s = time % 60;
  m = ((time / 60) | 0) % 60;
  h = ((time / 3600) | 0) % 24;

  // 2桁ずつ「:」で連結して返す
  return [h, m, s]
    .map(String)
    .join(':');
};

console.log(rectifyTime(str));

コードのポイント解説

この実装の流れを順番に見ていきましょう。

  1. 入力チェック: 空文字列が渡された場合は元の値をそのまま返し、正規表現 /^(\d\d):(\d\d):(\d\d)$/ を使って形式が正しいかどうかを検証します。形式が不正な場合は null を返します。
  2. 合計秒数への変換: 時・分・秒をそれぞれ数値に変換した後、「時 × 3600 + 分 × 60 + 秒」の式で合計秒数を求めます。これにより、分や秒が60を超えていても一括で扱えます。
  3. 各単位への再計算: 合計秒数を剰余演算とビット演算子(|0 による整数化)を使って、秒・分・時に分解します。% 24 を行うことで、24時間を超えた場合も対応可能です。
  4. 出力フォーマット: 最後に配列を文字列化して : で連結し、「HH:MM:SS」形式の文字列を組み立てます。

補足: 実務で利用する場合は、時・分・秒が1桁になったときにゼロパディングを行うとより堅牢になります。たとえば .map(n => String(n).padStart(2, '0')) のようにすると、「8:5:9」ではなく「08:05:09」という整形された結果が得られます。

実行結果

上記のコードを実行すると、コンソールには以下のように出力されます。

08:12:11

入力された「08:11:71」が、秒の繰り上がり処理によって「08:12:11」という正しい時間文字列へと修正されていることが確認できます。

まとめ

不正な時間文字列を修正する際は、まずすべてを合計秒数に変換してしまい、そこから再度各単位へ分解するのが最もシンプルで確実な方法です。このアプローチなら、分や秒がどれだけ大きくても、また24時間を超える場合でも柔軟に対応できます。日付・時刻処理はアプリケーションで頻繁に登場するため、こうした正規化ロジックはユーティリティ関数としてまとめておくと便利です。

  1. 【JavaScript】文字列が同一部分文字列の繰り返しで構成されているか判定する方法

    問題概要文字列を1つだけ引数として受け取り、その文字列が「ある部分文字列を複数回連結したもの」になっているかどうかを判定するJavaScript関数を実装します。たとえば、関数への入力が次の場合:const str = 'thisthisthisthis';期待される出力は以下のとおりです。const output = true;出力の説明この文字列は「this」という部分文字列を4回繰り返して構成されているため、true が返されます。実装コードこの問題を解くコードは次のようになります。const str = 'thisthisthisthis';const

  2. JavaScriptでスペースの位置を維持したまま文字列を反転させる方法

    問題空白(スペース)を含む可能性のある文字列を受け取り、各単語の文字順だけを反転させるJavaScript関数を作成することを考えます。求められる条件は次のとおりです。単語内部の文字は逆順に並べ替える単語と単語を区切るスペースの位置は元のまま維持する異なる単語の文字同士が入れ替わらないようにするアプローチ基本となるアイデアは、「元の文字列を末尾から先頭へ向かって走査し、空白以外の文字を結果用の文字列へ追加していく」というものです。文字を追加するたびに、結果文字列の現在の長さをインデックスとして元の文字列を参照し、その位置がスペースであれば同じくスペースを結果に加えます。こうすることで、スペース