1/*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { Log } from './Log';
17import i18n from '@ohos.i18n';
18import Intl from '@ohos.intl';
19
20const TAG: string = 'common_DateUtil';
21
22export class DateUtil {
23  public static readonly MILLISECONDS_PER_SECOND: number = 1000;
24  public static readonly SECONDS_PER_MINUTE: number = 60;
25  public static readonly SECONDS_PER_HOUR: number = 3600;
26  private static LANGUAGE_LOCALES_MAP = {
27    'zh': 'zh-CN',
28    'en': 'en-US'
29  };
30  private static readonly SECONDS_OF_ONE_DAY: number = 24 * 60 * 60;
31  private static dateTimeFormat: Intl.DateTimeFormat = new Intl.DateTimeFormat(DateUtil.getLocales(), {
32    year: 'numeric',
33    month: 'long',
34    day: 'numeric'
35  });
36  private static yearAndMonthFormat: Intl.DateTimeFormat = new Intl.DateTimeFormat(DateUtil.getLocales(), {
37    year: 'numeric',
38    month: 'long'
39  });
40  private static yearFormat: Intl.DateTimeFormat = new Intl.DateTimeFormat(DateUtil.getLocales(), {
41    year: 'numeric'
42  });
43
44  // Get the date after localization (year-month-day)
45  public static getLocalizedDate(milliseconds: number): string {
46    if(milliseconds === undefined){
47      milliseconds = new Date().getTime()
48    }
49    return this.dateTimeFormat.format(new Date(milliseconds));
50  }
51
52  public static format(time: Date, format_s?: string): string {
53    if (!format_s) {
54      return time.valueOf().toString();
55    }
56    let opts = {
57      'MM': time.getMonth() + 1,
58      'dd': time.getDate(),
59      'HH': time.getHours(),
60      'mm': time.getMinutes(),
61      'ss': time.getSeconds()
62    }
63
64    if (/(y+)/.test(format_s)) {
65      format_s = format_s.replace('yyyy', time.getFullYear().toString().substr(0));
66    }
67    for (let f in opts) {
68      if (new RegExp('(' + f + ')').test(format_s)) {
69        format_s = format_s.replace(f, (f.length == 1) ? opts[f] : (('00' + opts[f]).substr(
70          opts[f].toString().length)))
71      }
72    }
73    return format_s;
74  }
75
76  public static getDateTimeFormat(milliseconds: number): string {
77    return DateUtil.format(new Date(milliseconds), 'yyyy/MM/dd HH:mm:ss');
78  }
79
80  // Gets the localization date of the photo page grouping data
81  public static getGroupDataLocalizedDate(milliseconds: number): Resource {
82    let date = new Date(milliseconds);
83    let today = new Date();
84    if (date.getFullYear() == today.getFullYear() && date.getMonth() == today.getMonth()) {
85      if (date.getDate() == today.getDate()) {
86        return $r('app.string.date_today');
87      }
88      if (today.getDate() - date.getDate() == 1) {
89        return $r('app.string.date_yesterday');
90      }
91    }
92    return $r('app.string.common_place_holder', this.getLocalizedDate(milliseconds));
93  }
94
95  public static getLocalizedYear(milliseconds: number): Resource {
96    return $r('app.string.common_place_holder', this.yearFormat.format(new Date(milliseconds)).toString());
97  }
98
99  public static getLocalizedYearAndMonth(milliseconds: number): string {
100    return this.yearAndMonthFormat.format(new Date(milliseconds));
101  }
102
103  public static getLocalizedTime(milliseconds: number): string {
104    let locales: string = this.getLocales();
105    let is24HourClock = i18n.is24HourClock();
106    Log.info(TAG, `get is24HourClock ${is24HourClock}`);
107    return new Intl.DateTimeFormat(locales, {
108      hour: (!is24HourClock ? '2-digit' : 'numeric'),
109      minute: '2-digit'
110    }).format(new Date(milliseconds));
111  }
112
113  // Format duration
114  public static getFormattedDuration(milliSecond: number): string {
115    if (milliSecond == null) {
116      Log.error(TAG, 'getFormattedDuration, input is null!');
117      return '00:00';
118    }
119    if (milliSecond <= 0) {
120      Log.error(TAG, 'getFormattedDuration, input is negative number!');
121      return '00:00';
122    }
123    if (milliSecond < this.MILLISECONDS_PER_SECOND) {
124      return '00:01';
125    }
126    let seconds = Math.floor(milliSecond / this.MILLISECONDS_PER_SECOND);
127    let hourTime: number = Math.floor(seconds / this.SECONDS_PER_HOUR);
128    let minuteTime: number = Math.floor(Math.floor(seconds / this.SECONDS_PER_MINUTE) % this.SECONDS_PER_MINUTE);
129    let secondTime: number = Math.floor(seconds % this.SECONDS_PER_MINUTE);
130    if (hourTime > 0) {
131      return `${hourTime}:${this.checkTime(minuteTime)}:${this.checkTime(secondTime)}`;
132    } else {
133      return `${this.checkTime(minuteTime)}:${this.checkTime(secondTime)}`;
134    }
135  }
136
137  public static isTheSameDay(startTime: number, endTime: number): boolean {
138    if (startTime == null || endTime == null) {
139      return false;
140    }
141    const startTimeMs = new Date(startTime).setHours(0, 0, 0, 0);
142    const endTimeMs = new Date(endTime).setHours(0, 0, 0, 0);
143    return startTimeMs === endTimeMs ? true : false;
144  }
145
146  public static isTheSameYear(startTime: number, endTime: number): boolean {
147    if (startTime == null || endTime == null) {
148      return false;
149    }
150    const startYear = new Date(startTime).getFullYear();
151    const endYear = new Date(endTime).getFullYear();
152    return startYear === endYear ? true : false;
153  }
154
155  // Seconds converted to days (Less than 1 day is counted as 1 day)
156  public static convertSecondsToDays(seconds: number): number {
157    if (seconds % this.SECONDS_OF_ONE_DAY == 0) {
158      return seconds / this.SECONDS_OF_ONE_DAY;
159    } else {
160      return parseInt(seconds / this.SECONDS_OF_ONE_DAY + '') + 1;
161    }
162  }
163
164  public static isEmpty(obj: unknown): boolean {
165    return obj == undefined || obj == null;
166  }
167
168  private static getLocales(): string {
169    let systemLocale = i18n.getSystemLanguage();
170    let language = systemLocale.split('-')[0];
171    let locales: string = this.LANGUAGE_LOCALES_MAP['en'];
172    if (this.LANGUAGE_LOCALES_MAP[language]) {
173      locales = this.LANGUAGE_LOCALES_MAP[language];
174    }
175    return locales;
176  }
177
178  private static checkTime(time: number): string {
179    if (time < 0) {
180      Log.error(TAG, 'checkTime, input is negative number!');
181      return '00';
182    }
183    let formatTime: string = time.toString();
184    if (time < 10) {
185      let zeroString = '0';
186      formatTime = zeroString.concat(formatTime);
187    }
188    return formatTime;
189  }
190}