All files formater.ts

96.72% Statements 59/61
83.33% Branches 10/12
100% Functions 14/14
100% Lines 51/51

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95    1x   1x 12x   12x   12x   12x       12x   1x   1x   12x 12x 12x 12x 147x 21x   12x 12x 12x 12x 12x 12x 12x     132x 84x             12x 5x 5x     12x 7x 7x     12x 2x   2x     12x 1x   1x     1x 15x 15x 2x 2x     1x   15x   6x     12x 12x 12x 60x     21x       21x   1x  
// eslint-disable-next-line no-unused-vars
import Duration from './duration';
import FormatTokens from './formatTokens';
 
export default class Formater {
  private _hour: number = 0;
 
  private _minute: number = 0;
 
  private _second: number = 0;
 
  private _milliSecond: number = 0;
 
  private _inputTokens: Array<{type: string, token: string, value: number | string}>;
 
  private _formatTokens: {[key: string]: {type: string, func: Function, pad: number}} = {};
 
  static readonly FORMAT_EXPRESSION: RegExp = /\[.+?\]|\*?[Hh]+|\*?m+|\*?s+|\*?S|./g;
 
  static readonly TYPE_ORDER = ['hour', 'minute', 'second', 'millisecond', 'text'];
 
  constructor(private duration: Duration, private input: string) {
    const inputTokens = input.match(Formater.FORMAT_EXPRESSION);
    Iif (inputTokens === null) throw new Error('invalid token!');
    this._inputTokens = inputTokens.map((token) => {
      const type = FormatTokens.formatTokens.filter(types => types.token === token);
      return type.length === 0 ? { type: 'text', token, value: '' } : type[0];
    });
    this.addFormatToken('h', 'hour', this.calcHour);
    this.addFormatToken('hh', 'hour', this.calcHour, 2);
    this.addFormatToken('m', 'minute', this.calcMin);
    this.addFormatToken('mm', 'minute', this.calcMin, 2);
    this.addFormatToken('s', 'second', this.calcSec);
    this.addFormatToken('ss', 'second', this.calcSec, 2);
    this.addFormatToken('S', 'millisecond', this.calcMilliSec);
  }
 
  private addFormatToken(token: string, type: string, func: Function, pad: number = 0): void {
    this._formatTokens[token] = {
      type,
      func,
      pad,
    };
  }
 
  private calcHour = (): number => {
    this._hour = Math.floor(this.duration.millisecond / 3600000);
    return this._hour;
  }
 
  private calcMin = (): number => {
    this._minute = Math.floor((this.duration.millisecond - this._hour * 3600000) / 60000);
    return this._minute;
  }
 
  private calcSec = (): number => {
    this._second = Math.floor((this.duration.millisecond - this._hour * 3600000
      - this._minute * 60000) / 1000);
    return this._second;
  }
 
  private calcMilliSec = (): number => {
    this._milliSecond = this.duration.millisecond - this._hour * 3600000
      - this._minute * 60000 - this._second * 1000;
    return this._milliSecond;
  }
 
  private static zeroPad(value: number, length: number): string {
    let s = String(value);
    if (s.length >= length) return s;
    while (s.length < length) s = `0${s}`;
    return s;
  }
 
  private formatFunction(token: string): string {
    if (this._formatTokens[token] && typeof this._formatTokens[token].func === 'function') {
      return Formater.zeroPad(this._formatTokens[token].func(), this._formatTokens[token].pad);
    }
    return token.replace(/^\[/, '').replace(/\]$/, '');
  }
 
  public format(): string {
    Iif (this._inputTokens === null) return '';
    Formater.TYPE_ORDER.forEach((type) => {
      this._inputTokens.forEach((inputToken) => {
        if (type === inputToken.type) {
          // eslint-disable-next-line no-param-reassign
          inputToken.value = this.formatFunction(inputToken.token);
        }
      });
    });
    return this._inputTokens.map(inputToken => inputToken.value).join('');
  }
}