javascript-time-ago
Version:
Localized relative date/time formatting
189 lines (158 loc) • 6.31 kB
TypeScript
export type DateInput = Date | number;
export type Locale = string;
// Users can add custom styles via `TimeAgo.addLabels(locale, styleName, labels)`.
export type CustomLabelStyleName = string;
// There're also "legacy" label styles like "time" or "long-time" that have been deprecated.
// Users can still use those by adding them manually via `TimeAgo.addLabels()`.
export type LabelStyleName = 'long' | 'short' | 'narrow' | 'mini' | 'now' | CustomLabelStyleName;
export type Rounding = 'round' | 'floor';
// https://github.com/eemeli/make-plural/blob/master/packages/compiler/src/compile-range.js#L1
export type Count = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';
export type CommonUnit = 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second';
export type Unit = CommonUnit | 'quarter' | 'now';
export type CountLabels = {
[count in Count]?: string;
}
export interface PastAndFutureLabels {
past: string | CountLabels;
future: string | CountLabels;
previous?: string;
current?: string;
next?: string;
}
export interface PastAndFutureNowLabels {
past: string;
future: string;
current: string;
}
export type UnitLabels = string | CountLabels | PastAndFutureLabels
export type Labels = {
year: UnitLabels;
quarter?: UnitLabels;
month: UnitLabels;
week: UnitLabels;
day: UnitLabels;
hour: UnitLabels;
minute: UnitLabels;
second: UnitLabels;
}
export type UnitLabelsMini = string | CountLabels;
export type MiniLabels = {
year: UnitLabelsMini;
quarter?: UnitLabelsMini;
month: UnitLabelsMini;
week: UnitLabelsMini;
day: UnitLabelsMini;
hour: UnitLabelsMini;
minute: UnitLabelsMini;
second: UnitLabelsMini;
}
export type NowLabels = {
now: string | PastAndFutureNowLabels;
}
export type LocaleData = {
locale: Locale;
short: Labels;
narrow: Labels;
long: Labels;
mini?: MiniLabels;
now?: NowLabels;
}
export type FormatStyleName =
'round' |
'round-minute' |
'mini' |
'mini-now' |
'mini-minute' |
'mini-minute-now' |
'twitter' |
'twitter-now' |
'twitter-minute' |
'twitter-minute-now' |
'twitter-first-minute';
export type MinTimeFunction = (date: number, options: {
future: boolean,
getMinTimeForUnit: (unit: Unit, prevUnit?: Unit) => number | void
}) => number;
export interface Step {
formatAs?: Unit;
minTime?: number | MinTimeFunction;
format?(date: DateInput, locale: Locale, options: {
formatAs: (unit: Unit, amount: number) => string,
now: number,
future: boolean
}): string | void;
getTimeToNextUpdate?(date: DateInput, options: {
getTimeToNextUpdateForUnit: (unit: Unit) => number | void,
now: number,
future: boolean
}): number | void;
}
export interface Style {
steps: Step[];
labels: LabelStyleName | LabelStyleName[];
round?: Rounding;
}
interface FormatOptions {
now?: number;
future?: boolean;
round?: Rounding;
}
interface FormatOptionsWithGetTimeToNextUpdate extends FormatOptions {
getTimeToNextUpdate: boolean;
// `setTimeout()` function has a bug when it fires immediately
// when the delay is longer than about `24.85` days.
// https://stackoverflow.com/questions/3468607/why-does-settimeout-break-for-large-millisecond-delay-values
//
// In order to not burden the end users of this library with manually working around that bug,
// this library automatically caps the returned delay to a maximum value of about `24.85` days
// which still works correctly with `setTimeout()` function and doesn't break it.
//
// The end user of this library could still disable this automatic workaround
// by passing a `getTimeToNextUpdateUncapped: true` parameter.
// In that case, it will return the original non-modified uncapped delay
// which can be longer than `24.85` days and should be manually capped
// by the developer if it's going to be used in a `setTimeout()` call.
//
getTimeToNextUpdateUncapped?: boolean;
}
interface FormatOptionsWithRefresh extends FormatOptions {
refresh: (text: string) => void;
}
export default class TimeAgo {
// Creates a `TimeAgo` instance.
constructor(locale: Locale | Locale[], options?: { polyfill?: boolean });
// Calling `.format()` function normally.
format(date: DateInput, style?: FormatStyleName | Style, options?: FormatOptions): string;
// Calling `.format()` with `getTimeToNextUpdate: true` parameter.
//
// When `.format()` is called with `getTimeToNextUpdate: true` parameter,
// it returns an array containing the formatted time and the "time to next update" delay.
//
// Perhaps returning an array is not the best solution, and it would've been better
// to introduce a new function called `.formatAndGetTimeToNextUpdate()` or something like that.
// But at this stage it already returns an array and changing that would require
// a "major" version number update, and I would prefer not doing that for such an insignificant change.
//
format(date: DateInput, options: FormatOptionsWithGetTimeToNextUpdate): [string, number?];
format(date: DateInput, style: FormatStyleName | Style, options: FormatOptionsWithGetTimeToNextUpdate): [string, number?];
// Calling `.format()` with a `refresh()` parameter.
//
// When `.format()` is called with a `refresh()` parameter,
// it returns an array containing the formatted time and the "stop refreshing" function.
//
// I.e. it mimicks the return value of already-existing `getTimeToNextUpdate: true` parameter.
//
format(date: DateInput, options: FormatOptionsWithRefresh): [string, () => void];
format(date: DateInput, style: FormatStyleName | Style, options: FormatOptionsWithRefresh): [string, () => void];
// `getLabels()` function seems to be unused and is not documented.
// Perhaps it even wasn't ever declared as part of the public API
// and got in this TypeScript definition by accident.
//
// getLabels(labelsType: LabelStyleName | LabelStyleName[]): Labels;
static addLocale(localeData: LocaleData): void;
static addDefaultLocale(localeData: LocaleData): void;
static getDefaultLocale(): Locale;
static setDefaultLocale(locale: Locale): void;
static addLabels(locale: Locale, name: LabelStyleName, labels: Labels): void;
}