2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

1人フロントエンドAdvent Calendar 2023

Day 2

ミリ秒に対する変換を提供するmsパッケージ

Posted at

ms

msはVercelが開発するパッケージの1つです。このパッケージでは年や日、時間や分で記述された文字列をミリ秒に変換したりその逆を行うことができます。
ブラウザとNodeの両方で動作し、Edgeランタイムとの互換もあります。

ミリ秒への変換

例えば1時間のミリ秒を求めたい場合は以下のようにします。

import ms from 'ms';

// いずれも3600000
ms('1 Hour');
ms('1Hour');
ms('1 HOUR');
ms('1 hour');
ms('1 Hours');
ms('1 Hrs');
ms('1 Hr');
ms('1 H'):

HourHoursHrsHrHの文字列が数値の後ろに書かれていれば時間を基準として変換してくれます。これらの文字列は全てが大文字もしくは小文字でも同じように解釈されます。そして文字列と数値の間にはスペースがあっても同じようになります。
同じように年や週、日、分、秒がこの形式でミリ秒に変換できます。

ms('2 years'); // 63115200000
ms('1Week'); // 604800000
ms('10 DAYS'); // 864000000
ms('4 minutes'); // 240000
ms('7 sec'); // 7000

注意すべきところはこれらを組み合わせることができないというところです。

ms('2 years 1week'); // undefined

処理できない文字列の場合はundefinedが返ってきます。
単一のスケールに対応しているので組み合わせたい場合は以下のように足し合わせる必要があります。

ms('2 years') + ms('1 week'); // 63720000000

ミリ秒からの変換

数値を渡すことで先ほどの逆の変換を行えます。

ms(11111) // '11s'

変換後は一番大きいスケールだけが出力されることに注意してください。上記の例は11s111msを期待してしまいますが、11sが返ってきます。

第2引数にはオプションをオブジェクトで渡すことができます。現在はlongをキーに真偽値に値として取るオブジェクトを受け取っています。デフォルトは偽です。trueを渡すことで長い文字列をつけて結果を返します。

ms(11111, { long: true }) // "11 seconds"
ms(1111, { long: true }) // "1 second"

複数形の使い分けをしてくれるのがポイントです。

おまけ機能?

おまけと言って良いかわかりませんが、数値に変換できる文字列を渡したときは文字列から数値に変換した結果を返してくれます。

ms('111') // 111

1e10のような数値として扱える文字列を渡しても数値には変換されません(ミリ秒からの変換で数値型として渡すことはできます)。

ms('1e10') // undefined
ms(1e10) // 116d

型による工夫

msは執筆時のバージョン(2.1.3)では型の情報がついてきません。@types/msを用いることで型を付与することはできますが、ms関数にstringもしくはnumberならなんでも渡せるように定義されています。

// @types/ms@0.7.34から提供される型
/**
 * Short/Long format for `value`.
 *
 * @param {Number} value
 * @param {{long: boolean}} options
 * @return {String}
 */
declare function ms(value: number, options?: { long: boolean }): string;

/**
 * Parse the given `value` and return milliseconds.
 *
 * @param {String} value
 * @return {Number}
 */
declare function ms(value: string): number;

export = ms;

バージョン3からはmsから直接型を提供するようになります。現在は安定版としては提供されておらず、canaryバージョンを利用する必要があります。

// ms@3.0.0-canary.1から提供される型

declare type Unit = 'Years' | 'Year' | 'Yrs' | 'Yr' | 'Y' | 'Weeks' | 'Week' | 'W' | 'Days' | 'Day' | 'D' | 'Hours' | 'Hour' | 'Hrs' | 'Hr' | 'H' | 'Minutes' | 'Minute' | 'Mins' | 'Min' | 'M' | 'Seconds' | 'Second' | 'Secs' | 'Sec' | 's' | 'Milliseconds' | 'Millisecond' | 'Msecs' | 'Msec' | 'Ms';
declare type UnitAnyCase = Unit | Uppercase<Unit> | Lowercase<Unit>;
export declare type StringValue = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;
interface Options {
    /**
     * Set to `true` to use verbose formatting. Defaults to `false`.
     */
    long?: boolean;
}
/**
 * Parse or format the given `val`.
 *
 * @param value - The string or number to convert
 * @param options - Options for the conversion
 * @throws Error if `value` is not a non-empty string or a number
 */
declare function ms(value: StringValue, options?: Options): number;
declare function ms(value: number, options?: Options): string;
export default ms;

stringであればなんでも渡せたところからStringValueという型に絞られました。

まずは定義された他の型について見ていきます。UnitAnyCaseはスケールを表す文字列をユニオンで列挙したUnitを用いて以下のような型を提供します。

type UnitAnyCase = Unit | Uppercase<Unit> | Lowercase<Unit>;

つまり、Unitで列挙した文字列に加えてそれらを全て大文字にしたケース、小文字にしたケースを含めてユニオンとして持ちます。

StringValueはそれらを用いて以下の定義されます。

type StringValue = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;

number型を文字列にしたものか、それとUnitAnyCaseを結合したもの、その間にスペースをひとつ設けたものしか許可されません。
このようにmsは型を強く定義することで結果がundefinedとなることを事前に防げるような試みを行なっています(2020年のPRから3.0.0のリリースについて議論されているのでまだしばらく使えないかもしれません)。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?