// Modified version of internal Typescript intl.d.ts. // TODO(piloopin): remove when https://github.com/Microsoft/TypeScript/issues/3521 is shipped. declare module Intl { interface NumberFormatOptions { localeMatcher?: string; style?: string; currency?: string; currencyDisplay?: string; useGrouping?: boolean; minimumIntegerDigits?: number; minimumFractionDigits?: number; maximumFractionDigits?: number; } interface NumberFormat { format(value: number): string; } var NumberFormat: {new (locale?: string, options?: NumberFormatOptions): NumberFormat}; interface DateTimeFormatOptions { localeMatcher?: string; weekday?: string; era?: string; year?: string; month?: string; day?: string; hour?: string; minute?: string; second?: string; timeZoneName?: string; formatMatcher?: string; hour12?: boolean; } interface DateTimeFormat { format(date?: Date | number): string; } var DateTimeFormat: {new (locale?: string, options?: DateTimeFormatOptions): DateTimeFormat}; } export enum NumberFormatStyle { DECIMAL, PERCENT, CURRENCY } export class NumberFormatter { static format(number: number, locale: string, style: NumberFormatStyle, {minimumIntegerDigits = 1, minimumFractionDigits = 0, maximumFractionDigits = 3, currency, currencyAsSymbol = false}: { minimumIntegerDigits?: int, minimumFractionDigits?: int, maximumFractionDigits?: int, currency?: string, currencyAsSymbol?: boolean } = {}): string { var intlOptions: Intl.NumberFormatOptions = { minimumIntegerDigits: minimumIntegerDigits, minimumFractionDigits: minimumFractionDigits, maximumFractionDigits: maximumFractionDigits }; intlOptions.style = NumberFormatStyle[style].toLowerCase(); if (style == NumberFormatStyle.CURRENCY) { intlOptions.currency = currency; intlOptions.currencyDisplay = currencyAsSymbol ? 'symbol' : 'code'; } return new Intl.NumberFormat(locale, intlOptions).format(number); } } function digitCondition(len: int): string { return len == 2 ? '2-digit' : 'numeric'; } function nameCondition(len: int): string { return len < 4 ? 'short' : 'long'; } function extractComponents(pattern: string): Intl.DateTimeFormatOptions { var ret: Intl.DateTimeFormatOptions = {}; var i = 0, j; while (i < pattern.length) { j = i; while (j < pattern.length && pattern[j] == pattern[i]) j++; let len = j - i; switch (pattern[i]) { case 'G': ret.era = nameCondition(len); break; case 'y': ret.year = digitCondition(len); break; case 'M': if (len >= 3) ret.month = nameCondition(len); else ret.month = digitCondition(len); break; case 'd': ret.day = digitCondition(len); break; case 'E': ret.weekday = nameCondition(len); break; case 'j': ret.hour = digitCondition(len); break; case 'h': ret.hour = digitCondition(len); ret.hour12 = true; break; case 'H': ret.hour = digitCondition(len); ret.hour12 = false; break; case 'm': ret.minute = digitCondition(len); break; case 's': ret.second = digitCondition(len); break; case 'z': ret.timeZoneName = 'long'; break; case 'Z': ret.timeZoneName = 'short'; break; } i = j; } return ret; } var dateFormatterCache: Map = new Map(); export class DateFormatter { static format(date: Date, locale: string, pattern: string): string { var key = locale + pattern; if (dateFormatterCache.has(key)) { return dateFormatterCache.get(key).format(date); } var formatter = new Intl.DateTimeFormat(locale, extractComponents(pattern)); dateFormatterCache.set(key, formatter); return formatter.format(date); } }