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'):
Hour
、Hours
、Hrs
、Hr
、H
の文字列が数値の後ろに書かれていれば時間を基準として変換してくれます。これらの文字列は全てが大文字もしくは小文字でも同じように解釈されます。そして文字列と数値の間にはスペースがあっても同じようになります。
同じように年や週、日、分、秒がこの形式でミリ秒に変換できます。
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のリリースについて議論されているのでまだしばらく使えないかもしれません)。