summaryrefslogtreecommitdiffhomepage
path: root/gui/src/shared/date-helper.ts
blob: 36353c9b4400923e46ed2ba4cfa35d2cdc7436ec (plain)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { sprintf } from 'sprintf-js';
import { messages } from './gettext';

export type DateType = Date | string | number;

export enum DateComponent {
  day,
  hour,
  minute,
}

export function dateByAddingComponent(date: DateType, component: DateComponent, value: number) {
  const modifiedDate = new Date(date);
  switch (component) {
    case DateComponent.day:
      modifiedDate.setDate(modifiedDate.getDate() + value);
      break;
    case DateComponent.hour:
      modifiedDate.setHours(modifiedDate.getHours() + value);
      break;
    case DateComponent.minute:
      modifiedDate.setMinutes(modifiedDate.getMinutes() + value);
      break;
  }

  return modifiedDate;
}

export class DateDiff {
  private readonly fromDate: Date;
  private readonly toDate: Date;

  public constructor(fromDate: DateType, toDate: DateType) {
    this.fromDate = new Date(fromDate);
    this.toDate = new Date(toDate);
  }

  get milliseconds(): number {
    return this.toDate.getTime() - this.fromDate.getTime();
  }

  get seconds(): number {
    return this.floor(this.milliseconds / 1000);
  }

  get minutes(): number {
    return this.floor(this.seconds / 60);
  }

  get hours(): number {
    return this.floor(this.minutes / 60);
  }

  get days(): number {
    return this.floor(this.hours / 24);
  }

  get months(): number {
    const months = new Date(Math.abs(this.milliseconds)).getUTCMonth();
    const monthsWithSign = this.milliseconds >= 0 ? months : -months;
    return this.years * 12 + monthsWithSign;
  }

  get years(): number {
    const years = new Date(Math.abs(this.milliseconds)).getUTCFullYear() - 1970;
    return this.milliseconds >= 0 ? years : -years;
  }

  private floor(n: number): number {
    return n >= 0 ? Math.floor(n) : Math.ceil(n);
  }
}

export function formatRelativeDate(
  fromDate: DateType,
  toDate: DateType,
  withSuffix = false,
): string {
  const diff = new DateDiff(fromDate, toDate);
  const years = Math.abs(diff.years);
  const months = Math.abs(diff.months);
  const days = Math.abs(diff.days);
  const hours = Math.abs(diff.hours);
  const minutes = Math.abs(diff.minutes);

  if (!withSuffix) {
    if (years > 0) {
      return sprintf(messages.ngettext('1 year', '%d years', years), years);
    } else if (months >= 3) {
      return sprintf(messages.ngettext('1 month', '%d months', months), months);
    } else if (days > 0) {
      return sprintf(messages.ngettext('1 day', '%d days', days), days);
    } else {
      return messages.gettext('less than a day');
    }
  } else if (diff.milliseconds > 0) {
    if (years > 0) {
      return sprintf(messages.ngettext('1 year left', '%d years left', years), years);
    } else if (months >= 3) {
      return sprintf(messages.ngettext('1 month left', '%d months left', months), months);
    } else if (days > 0) {
      return sprintf(messages.ngettext('1 day left', '%d days left', days), days);
    } else {
      return messages.gettext('less than a day left');
    }
  } else {
    if (years > 0) {
      return sprintf(messages.ngettext('a year ago', '%d years ago', years), years);
    } else if (months > 0) {
      return sprintf(messages.ngettext('a month ago', '%d months ago', months), months);
    } else if (days > 0) {
      return sprintf(messages.ngettext('a day ago', '%d days ago', days), days);
    } else if (hours > 0) {
      return sprintf(messages.ngettext('an hour ago', '%d hours ago', hours), hours);
    } else if (minutes > 0) {
      return sprintf(messages.ngettext('a minute ago', '%d minutes ago', minutes), minutes);
    } else {
      return messages.gettext('less than a minute ago');
    }
  }
}