Parcourir la source

chore: use `Intl` for date formatting (#3588)

* chore: use `Intl` for date formatting

* fix: show last traffic reset

* chore: use raw timestamps

* fix: remove unnecessary import
Danil S. il y a 1 jour
Parent
commit
70f6d6b21a

+ 0 - 151
web/assets/js/util/date-util.js

@@ -1,151 +0,0 @@
-const oneMinute = 1000 * 60;  // MilliseConds in a Minute
-const oneHour = oneMinute * 60;  // The milliseconds of one hour
-const oneDay = oneHour * 24; // The Number of MilliseConds A Day
-const oneWeek = oneDay * 7; // The milliseconds per week
-const oneMonth = oneDay * 30; // The milliseconds of a month
-
-/**
- * Decrease according to the number of days
- *
- * @param days to reduce the number of days to be reduced
- */
-Date.prototype.minusDays = function (days) {
-    return this.minusMillis(oneDay * days);
-};
-
-/**
- * Increase according to the number of days
- *
- * @param days The number of days to be increased
- */
-Date.prototype.plusDays = function (days) {
-    return this.plusMillis(oneDay * days);
-};
-
-/**
- * A few
- *
- * @param hours to be reduced
- */
-Date.prototype.minusHours = function (hours) {
-    return this.minusMillis(oneHour * hours);
-};
-
-/**
- * Increase hourly
- *
- * @param hours to increase the number of hours
- */
-Date.prototype.plusHours = function (hours) {
-    return this.plusMillis(oneHour * hours);
-};
-
-/**
- * Make reduction in minutes
- *
- * @param minutes to reduce the number of minutes
- */
-Date.prototype.minusMinutes = function (minutes) {
-    return this.minusMillis(oneMinute * minutes);
-};
-
-/**
- * Add in minutes
- *
- * @param minutes to increase the number of minutes
- */
-Date.prototype.plusMinutes = function (minutes) {
-    return this.plusMillis(oneMinute * minutes);
-};
-
-/**
- * Decrease in milliseconds
- *
- * @param millis to reduce the milliseconds
- */
-Date.prototype.minusMillis = function(millis) {
-    let time = this.getTime() - millis;
-    let newDate = new Date();
-    newDate.setTime(time);
-    return newDate;
-};
-
-/**
- * Add in milliseconds to increase
- *
- * @param millis to increase the milliseconds to increase
- */
-Date.prototype.plusMillis = function(millis) {
-    let time = this.getTime() + millis;
-    let newDate = new Date();
-    newDate.setTime(time);
-    return newDate;
-};
-
-/**
- * Setting time is 00: 00: 00.000 on the day
- */
-Date.prototype.setMinTime = function () {
-    this.setHours(0);
-    this.setMinutes(0);
-    this.setSeconds(0);
-    this.setMilliseconds(0);
-    return this;
-};
-
-/**
- * Setting time is 23: 59: 59.999 on the same day
- */
-Date.prototype.setMaxTime = function () {
-    this.setHours(23);
-    this.setMinutes(59);
-    this.setSeconds(59);
-    this.setMilliseconds(999);
-    return this;
-};
-
-/**
- * Formatting date
- */
-Date.prototype.formatDate = function () {
-    return this.getFullYear() + "-" + NumberFormatter.addZero(this.getMonth() + 1) + "-" + NumberFormatter.addZero(this.getDate());
-};
-
-/**
- * Format time
- */
-Date.prototype.formatTime = function () {
-    return NumberFormatter.addZero(this.getHours()) + ":" + NumberFormatter.addZero(this.getMinutes()) + ":" + NumberFormatter.addZero(this.getSeconds());
-};
-
-/**
- * Formatting date plus time
- *
- * @param split Date and time separation symbols, default is a space
- */
-Date.prototype.formatDateTime = function (split = ' ') {
-    return this.formatDate() + split + this.formatTime();
-};
-
-class DateUtil {
-    // String to date object
-    static parseDate(str) {
-        return new Date(str.replace(/-/g, '/'));
-    }
-
-    static formatMillis(millis) {
-        return moment(millis).format('YYYY-M-D HH:mm:ss');
-    }
-
-    static firstDayOfMonth() {
-        const date = new Date();
-        date.setDate(1);
-        date.setMinTime();
-        return date;
-    }
-
-    static convertToJalalian(date) {
-        return date && moment.isMoment(date) ? date.format('jYYYY/jMM/jDD HH:mm:ss') : null;
-    }
-
-}

+ 31 - 0
web/assets/js/util/index.js

@@ -882,4 +882,35 @@ class FileManager {
 
         link.remove();
     }
+}
+
+class IntlUtil {
+    static formatDate(date) {
+        const language = LanguageManager.getLanguage()
+
+        let intlOptions = {
+            year: "numeric",
+            month: "numeric",
+            day: "numeric",
+            hour: "numeric",
+            minute: "numeric",
+            second: "numeric"
+        }
+
+        const intl = new Intl.DateTimeFormat(
+            language,
+            intlOptions
+        )
+
+        return intl.format(new Date(date))
+    }
+    static formatRelativeTime(date) {
+        const language = LanguageManager.getLanguage()
+        const now = new Date()
+
+        const diff = Math.round((date - now) / (1000 * 60 * 60 * 24))
+        const formatter = new Intl.RelativeTimeFormat(language, { numeric: 'auto' })
+
+        return formatter.format(diff, 'day');
+    }
 }

+ 0 - 1
web/html/common/page.html

@@ -44,7 +44,6 @@
 <script src="{{ .base_path }}assets/axios/axios.min.js?{{ .cur_ver }}"></script>
 <script src="{{ .base_path }}assets/qs/qs.min.js"></script>
 <script src="{{ .base_path }}assets/js/axios-init.js?{{ .cur_ver }}"></script>
-<script src="{{ .base_path }}assets/js/util/date-util.js?{{ .cur_ver }}"></script>
 <script src="{{ .base_path }}assets/js/util/index.js?{{ .cur_ver }}"></script>
 <script>
   const basePath = '{{ .base_path }}';

+ 14 - 56
web/html/component/aClientTable.html

@@ -111,20 +111,12 @@
   <template v-if="client.expiryTime !=0 && client.reset >0">
     <a-popover :overlay-class-name="themeSwitcher.currentTheme">
       <template slot="content">
-        <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}
-        </span>
-        <span v-else>
-          <template v-if="app.datepicker === 'gregorian'">
-            [[ DateUtil.formatMillis(client._expiryTime) ]]
-          </template>
-          <template v-else>
-            [[ DateUtil.convertToJalalian(moment(client._expiryTime)) ]]
-          </template>
-        </span>
+        <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}</span>
+        <span v-else>[[ IntlUtil.formatDate(client.expiryTime) ]]</span>
       </template>
       <table>
         <tr class="tr-table-box">
-          <td class="tr-table-rt"> [[ remainedDays(client.expiryTime) ]] </td>
+          <td class="tr-table-rt"> [[ IntlUtil.formatRelativeTime(client.expiryTime) ]] </td>
           <td class="infinite-bar tr-table-bar">
             <a-progress :show-info="false" :status="isClientDepleted(record, client.email)? 'exception' : ''" :percent="expireProgress(client.expiryTime, client.reset)" />
           </td>
@@ -136,18 +128,10 @@
   <template v-else>
     <a-popover v-if="client.expiryTime != 0" :overlay-class-name="themeSwitcher.currentTheme">
       <template slot="content">
-        <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}
-        </span>
-        <span v-else>
-          <template v-if="app.datepicker === 'gregorian'">
-            [[ DateUtil.formatMillis(client._expiryTime) ]]
-          </template>
-          <template v-else>
-            [[ DateUtil.convertToJalalian(moment(client._expiryTime)) ]]
-          </template>
-        </span>
+        <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}</span>
+        <span v-else>[[ IntlUtil.formatDate(client.expiryTime) ]]</span>
       </template>
-      <a-tag :style="{ minWidth: '50px', border: 'none' }" :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)"> [[ remainedDays(client.expiryTime) ]] </a-tag>
+      <a-tag :style="{ minWidth: '50px', border: 'none' }" :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)"> [[ IntlUtil.formatRelativeTime(client.expiryTime) ]] </a-tag>
     </a-popover>
     <a-tag v-else :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)" :style="{ border: 'none' }" class="infinite-tag">
       <svg height="10px" width="14px" viewBox="0 0 640 512" fill="currentColor">
@@ -232,20 +216,12 @@
         </tr>
         <tr>
           <template v-if="client.expiryTime !=0 && client.reset >0">
-            <td width="80px" :style="{ margin: '0', textAlign: 'right', fontSize: '1em' }"> [[ remainedDays(client.expiryTime) ]] </td>
+            <td width="80px" :style="{ margin: '0', textAlign: 'right', fontSize: '1em' }"> [[ IntlUtil.formatRelativeTime(client.expiryTime) ]] </td>
             <td width="120px" class="infinite-bar">
               <a-popover :overlay-class-name="themeSwitcher.currentTheme">
                 <template slot="content">
-                  <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}
-                  </span>
-                  <span v-else>
-                    <template v-if="app.datepicker === 'gregorian'">
-                      [[ DateUtil.formatMillis(client._expiryTime) ]]
-                    </template>
-                    <template v-else>
-                      [[ DateUtil.convertToJalalian(moment(client._expiryTime)) ]]
-                    </template>
-                  </span>
+                  <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}</span>
+                  <span v-else>[[ IntlUtil.formatDate(client.expiryTime) ]]</span>
                 </template>
                 <a-progress :show-info="false" :status="isClientDepleted(record, client.email)? 'exception' : ''" :percent="expireProgress(client.expiryTime, client.reset)" />
               </a-popover>
@@ -256,18 +232,10 @@
             <td colspan="3" :style="{ textAlign: 'center' }">
               <a-popover v-if="client.expiryTime != 0" :overlay-class-name="themeSwitcher.currentTheme">
                 <template slot="content">
-                  <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}
-                  </span>
-                  <span v-else>
-                    <template v-if="app.datepicker === 'gregorian'">
-                      [[ DateUtil.formatMillis(client._expiryTime) ]]
-                    </template>
-                    <template v-else>
-                      [[ DateUtil.convertToJalalian(moment(client._expiryTime)) ]]
-                    </template>
-                  </span>
+                  <span v-if="client.expiryTime < 0">{{ i18n "pages.client.delayedStart" }}</span>
+                  <span v-else>[[ IntlUtil.formatDate(client.expiryTime) ]]</span>
                 </template>
-                <a-tag :style="{ minWidth: '50px', border: 'none' }" :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)"> [[ remainedDays(client.expiryTime) ]] </a-tag>
+                <a-tag :style="{ minWidth: '50px', border: 'none' }" :color="ColorUtils.userExpiryColor(app.expireDiff, client, themeSwitcher.isDarkTheme)"> [[ IntlUtil.formatRelativeTime(client.expiryTime) ]] </a-tag>
               </a-popover>
               <a-tag v-else :color="client.enable ? 'purple' : themeSwitcher.isDarkTheme ? '#2c3950' : '#bcbcbc'" class="infinite-tag">
                 <svg height="10px" width="14px" viewBox="0 0 640 512" fill="currentColor">
@@ -289,12 +257,7 @@
 </template>
 <template slot="createdAt" slot-scope="text, client, index">
   <template v-if="client.created_at">
-    <template v-if="app.datepicker === 'gregorian'">
-      [[ DateUtil.formatMillis(client.created_at) ]]
-    </template>
-    <template v-else>
-      [[ DateUtil.convertToJalalian(moment(client.created_at)) ]]
-    </template>
+    [[ IntlUtil.formatDate(client.created_at) ]]
   </template>
   <template v-else>
     -
@@ -302,12 +265,7 @@
 </template>
 <template slot="updatedAt" slot-scope="text, client, index">
   <template v-if="client.updated_at">
-    <template v-if="app.datepicker === 'gregorian'">
-      [[ DateUtil.formatMillis(client.updated_at) ]]
-    </template>
-    <template v-else>
-      [[ DateUtil.convertToJalalian(moment(client.updated_at)) ]]
-    </template>
+    [[ IntlUtil.formatDate(client.updated_at) ]]
   </template>
   <template v-else>
     -

+ 1 - 3
web/html/form/inbound.html

@@ -52,9 +52,7 @@
                     <br v-if="dbInbound.lastTrafficResetTime && dbInbound.lastTrafficResetTime > 0">
                     <span v-if="dbInbound.lastTrafficResetTime && dbInbound.lastTrafficResetTime > 0">
                         <strong>{{ i18n "pages.inbounds.lastReset" }}:</strong>
-                        <span v-if="datepicker == 'gregorian'">[[
-                            moment(dbInbound.lastTrafficResetTime).format('YYYY-MM-DD HH:mm:ss') ]]</span>
-                        <span v-else>[[ DateUtil.convertToJalalian(moment(dbInbound.lastTrafficResetTime)) ]]</span>
+                        <span>[[ IntlUtil.formatDate(dbInbound.lastTrafficResetTime) ]]</span>
                     </span>
                 </template>
                 {{ i18n "pages.inbounds.periodicTrafficResetTitle" }}

+ 5 - 23
web/html/inbounds.html

@@ -384,15 +384,12 @@
                     </template>
                     <template slot="expiryTime" slot-scope="text, dbInbound">
                       <a-popover v-if="dbInbound.expiryTime > 0" :overlay-class-name="themeSwitcher.currentTheme">
-                        <template slot="content" v-if="app.datepicker === 'gregorian'">
-                          [[ DateUtil.formatMillis(dbInbound.expiryTime) ]]
-                        </template>
-                        <template v-else slot="content">
-                          [[ DateUtil.convertToJalalian(moment(dbInbound.expiryTime)) ]]
+                        <template slot="content">
+                          [[ IntlUtil.formatDate(dbInbound.expiryTime) ]]
                         </template>
                         <a-tag :style="{ minWidth: '50px' }"
                           :color="ColorUtils.usageColor(new Date().getTime(), app.expireDiff, dbInbound._expiryTime)">
-                          [[ remainedDays(dbInbound._expiryTime) ]]
+                          [[ IntlUtil.formatRelativeTime(dbInbound.expiryTime) ]]
                         </a-tag>
                       </a-popover>
                       <a-tag v-else color="purple" class="infinite-tag">
@@ -549,12 +546,7 @@
                               <td>
                                 <a-tag :style="{ minWidth: '50px', textAlign: 'center' }"
                                   v-if="dbInbound.expiryTime > 0" :color="dbInbound.isExpiry? 'red': 'blue'">
-                                  <template v-if="app.datepicker === 'gregorian'">
-                                    [[ DateUtil.formatMillis(dbInbound.expiryTime) ]]
-                                  </template>
-                                  <template v-else>
-                                    [[ DateUtil.convertToJalalian(moment(dbInbound.expiryTime)) ]]
-                                  </template>
+                                  [[ IntlUtil.formatDate(dbInbound.expiryTime) ]]
                                 </a-tag>
                                 <a-tag v-else :style="{ textAlign: 'center' }" color="purple" class="infinite-tag">
                                   <svg height="10px" width="14px" viewBox="0 0 640 512" fill="currentColor">
@@ -1407,13 +1399,6 @@
         if (remainedSeconds >= resetSeconds) return 0;
         return 100 * (1 - (remainedSeconds / resetSeconds));
       },
-      remainedDays(expTime) {
-        if (expTime == 0) return null;
-        if (expTime < 0) return TimeFormatter.formatSecond(expTime / -1000);
-        now = new Date().getTime();
-        if (expTime < now) return '{{ i18n "depleted" }}';
-        return TimeFormatter.formatSecond((expTime - now) / 1000);
-      },
       statsExpColor(dbInbound, email) {
         if (email.length == 0) return '#7a316f';
         clientStats = dbInbound.clientStats.find(stats => stats.email === email);
@@ -1458,10 +1443,7 @@
       formatLastOnline(email) {
         const ts = this.getLastOnline(email)
         if (!ts) return '-'
-        if (this.datepicker === 'gregorian') {
-          return DateUtil.formatMillis(ts)
-        }
-        return DateUtil.convertToJalalian(moment(ts))
+        return IntlUtil.formatDate(ts)
       },
       isRemovable(dbInboundId) {
         return this.getInboundClients(this.dbInbounds.find(row => row.id === dbInboundId)).length > 1;

+ 1 - 3
web/html/index.html

@@ -844,11 +844,9 @@
             text = `<td>${log.Email}</td>`;
           }
 
-          const { locale, timeZone } = Intl.DateTimeFormat().resolvedOptions();
-
           formattedLogs += `
 <tr ${outboundColor}>
-    <td><b>${new Date(log.DateTime).toLocaleString(locale, { timeZone })}</b></td>
+    <td><b>${IntlUtil.formatDate(log.DateTime)}</b></td>
     <td>${log.FromAddress}</td>
     <td>${log.ToAddress}</td>
     <td>${log.Inbound}</td>

+ 3 - 18
web/html/modals/inbound_info_modal.html

@@ -199,12 +199,7 @@
           <td>{{ i18n "pages.inbounds.createdAt" }}</td>
           <td>
             <template v-if="infoModal.clientSettings && infoModal.clientSettings.created_at">
-              <template v-if="app.datepicker === 'gregorian'">
-                <a-tag>[[ DateUtil.formatMillis(infoModal.clientSettings.created_at) ]]</a-tag>
-              </template>
-              <template v-else>
-                <a-tag>[[ DateUtil.convertToJalalian(moment(infoModal.clientSettings.created_at)) ]]</a-tag>
-              </template>
+              <a-tag>[[ IntlUtil.formatDate(infoModal.clientSettings.created_at) ]]</a-tag>
             </template>
             <template v-else>
               <a-tag>-</a-tag>
@@ -215,12 +210,7 @@
           <td>{{ i18n "pages.inbounds.updatedAt" }}</td>
           <td>
             <template v-if="infoModal.clientSettings && infoModal.clientSettings.updated_at">
-              <template v-if="app.datepicker === 'gregorian'">
-                <a-tag>[[ DateUtil.formatMillis(infoModal.clientSettings.updated_at) ]]</a-tag>
-              </template>
-              <template v-else>
-                <a-tag>[[ DateUtil.convertToJalalian(moment(infoModal.clientSettings.updated_at)) ]]</a-tag>
-              </template>
+              <a-tag>[[ IntlUtil.formatDate(infoModal.clientSettings.updated_at) ]]</a-tag>
             </template>
             <template v-else>
               <a-tag>-</a-tag>
@@ -282,12 +272,7 @@
           <td>
             <template v-if="infoModal.clientSettings.expiryTime > 0">
               <a-tag :color="ColorUtils.usageColor(new Date().getTime(), app.expireDiff, infoModal.clientSettings.expiryTime)"> 
-                <template v-if="app.datepicker === 'gregorian'">
-                  [[ DateUtil.formatMillis(infoModal.clientSettings.expiryTime) ]]
-                </template>
-                <template v-else>
-                  [[ DateUtil.convertToJalalian(moment(infoModal.clientSettings.expiryTime)) ]]
-                </template>
+                [[ IntlUtil.formatDate(infoModal.clientSettings.expiryTime) ]]
               </a-tag>
             </template>
             <a-tag v-else-if="infoModal.clientSettings.expiryTime < 0" color="green">[[ infoModal.clientSettings.expiryTime / -86400000 ]] {{ i18n "pages.client.days" }}

+ 2 - 23
web/html/settings/panel/subscription/subpage.html

@@ -4,7 +4,6 @@
 <script src="{{ .base_path }}assets/vue/vue.min.js?{{ .cur_ver }}"></script>
 <script src="{{ .base_path }}assets/ant-design-vue/antd.min.js"></script>
 <script src="{{ .base_path }}assets/js/util/index.js?{{ .cur_ver }}"></script>
-<script src="{{ .base_path }}assets/js/util/date-util.js?{{ .cur_ver }}"></script>
 <script src="{{ .base_path }}assets/qrcode/qrious2.min.js?{{ .cur_ver }}"></script>
 {{ template "page/head_end" .}}
 
@@ -141,17 +140,7 @@
                                 <a-descriptions-item
                                     label='{{ i18n "lastOnline" }}'>
                                     <template v-if="app.lastOnlineMs > 0">
-                                        <template
-                                            v-if="app.datepicker === 'gregorian'">
-                                            [[
-                                            DateUtil.formatMillis(app.lastOnlineMs)
-                                            ]]
-                                        </template>
-                                        <template v-else>
-                                            [[
-                                            DateUtil.convertToJalalian(moment(app.lastOnlineMs))
-                                            ]]
-                                        </template>
+                                        [[ IntlUtil.formatDate(app.lastOnlineMs) ]]
                                     </template>
                                     <template v-else>
                                         <span>-</span>
@@ -163,17 +152,7 @@
                                         {{ i18n "subscription.noExpiry" }}
                                     </template>
                                     <template v-else>
-                                        <template
-                                            v-if="app.datepicker === 'gregorian'">
-                                            [[
-                                            DateUtil.formatMillis(app.expireMs)
-                                            ]]
-                                        </template>
-                                        <template v-else>
-                                            [[
-                                            DateUtil.convertToJalalian(moment(app.expireMs))
-                                            ]]
-                                        </template>
+                                        [[ IntlUtil.formatDate(app.expireMs) ]]
                                     </template>
                                 </a-descriptions-item>
                             </a-descriptions>