summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/shared/date-helper.ts121
1 files changed, 121 insertions, 0 deletions
diff --git a/gui/src/shared/date-helper.ts b/gui/src/shared/date-helper.ts
new file mode 100644
index 0000000000..0011ed8fc2
--- /dev/null
+++ b/gui/src/shared/date-helper.ts
@@ -0,0 +1,121 @@
+import { sprintf } from 'sprintf-js';
+import { messages } from './gettext';
+
+export type DateType = Date | string;
+
+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');
+ }
+ }
+}