Angular:日期时区全局参数设置

Angular: Date Timezone Global parameter setting

我正在寻找方法

如何做到这一点? Angular 中是否有一个全局参数来设置它,也许在配置文件中?

*我们代码库中有500行日期代码,需要这个全局转换。有时当人们在不同的时区工作时,应用程序会呈现不同的时区日期。需要更正以前人的代码。

目前无法将这些行转换为 Moment,在当前代码库中使用 Date。

此外,这是一个合适的解决方案吗? tzutil /s "Pacific Standard Time" ,刚刚在 google

中了解到这个

https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh875624(v=ws.11)

处理日期会让您发疯。使用客户端日期的最大问题是您必须依赖正确设置日期、时间和时区的客户端机器。您始终最好在服务器上创建日期,这样您就可以控制时钟。

拥有一个 api 端点,returns 一个适合你的约会对象是最可靠的选择。往返服务器的开销是非常值得的。

我完全同意@Adrian Brand 的观点。此外,这不是 Angular 问题。这更像是您在申请中处理约会时间的方式。

根据我的经验。使用内置 JavaScript Date.

来做这个日期时间的事情总是很棘手

此外,为了处理太平洋时间,您可能需要处理夏令时。这本身就是另一个问题。

The Pacific Time Zone (PT) is a time zone encompassing parts of western Canada, the western United States, and western Mexico. Places in this zone observe standard time by subtracting eight hours from Coordinated Universal Time (UTC−08:00). During daylight saving time, a time offset of UTC−07:00 is used.

我假设您仍将数据作为 ISO 格式发送到服务器。


所以我在新加坡,请参阅以下正常 Date 构造函数的结果。

  1. var date = new Date(2019, 3, 5)。 //Fri Apr 05 2019 00:00:00 GMT+0800 (Singapore Standard Time)
  2. date.toISOString() //2019-04-04T16:00:00.000Z。因为新加坡是 +08:00,比 UTC 早 8 小时。

因此,如果您希望始终执行新日期以得到 PST 时间,这意味着

  1. var date = new Date(2019, 3, 5) // Fri Apr 05 2019 00:00:00 GMT-0700 (Pacific Standard Time)
  2. date.toISOString() //2019-04-05T08:00:00.000Z。因为太平洋标准时间 -08:00,比 UTC 晚 8 小时。 -07:00的夏令时话题,我留给你

您需要

  1. 重写 Date 构造函数,完全不推荐这样做。
  2. 在日期构造中添加一个新方法来显示或给你一个正确的 ISO 格式,但要考虑 PST 时区。这涉及一些字符串替换和一些用于偏移计算的数学运算。

添加在 PST 中显示字符串的方法

如果您使用 var date = new Date(2019, 3, 5) 的确切日期执行构造函数。您只需添加一个新方法调用 toPSTString() 并使用正则表达式将 () 中的文本替换为 Pacific Standard Time 并将 GMT+xxx 中的文本替换为 GMT-08:00 因为值日期是绝对的。

Date.prototype.toPSTString = function () {
  let date = this.toString();
  //date.replace.... easy part, you could use Regex to do it
  return date;
};

但是如果您在构造函数中传递了 ISO String 格式的日期或毫秒数。处理起来会非常棘手。例如,如果你做 new Date("2019-04-05T07:00:00.000Z"),你想看到什么?

见下文,了解我如何根据偏移量差异输出 ISO 字符串。它可能会给你一些想法/

添加一种方法来获取考虑 PST -08:00 时区的 ISO 格式的字符串

new Date 将始终在您的本地计算机时区工作。所以如果我在新加坡,我做 new Date(2019, 3, 5).toISOString(),它总是给我 2019-04-04T16:00:00.000Z,而不是你期望的 2019-04-05T08:00:00.000Z

您也可以覆盖 JS 函数以输出 UTC 日期,但要考虑 PST 时间。

Date.prototype.toPSTString = function () {
  function convertMinuteToMillisecond(mins) {
    return mins * 60 * 1000;
  }
  let localDateOffsetToUtc = this.getTimezoneOffset(); //the offset between the user local timezone with UTC. In my use case of Singapore, it give me -480.
  const offSetBetweenPSTAndUTC = 480;
  let offsetBetweenPSTAndLocal = offSetBetweenPSTAndUTC - localDateOffsetToUtc;
  let newDate = new Date(
    this.getTime() + convertMinuteToMillisecond(offsetBetweenPSTAndLocal)
  );
  return newDate.toISOString();
};

var date = new Date(2019, 3, 5);
date.toISOString(); //"2019-04-04T16:00:00.000Z" Singapore
date.toPSTString(); //"2019-04-05T08:00:00.000Z" PST

输出看起来是正确的。我还没有真正测试过,但希望你能明白。


但通常情况下,如果您在新加坡,您希望看到新加坡时区的日期。没有人关心 PST 时区。如果您在伦敦,也一样,您不想看到新加坡或 PST 时区的时间。我想你可能想考虑一下。因为如果您的应用程序正在成长,修复此类问题会变得越来越困难。

我写了我如何 handle the timezone and locale in my blog。在我的用例中,我使用 moment.js 而且,服务器端需要在这方面支持我。如果你想有更多的想法,你也可以看看

这应该可以做到。

传入 null 以获取太平洋日期 now,或传入任何日期以将其转换为太平洋日期:

pacificTimeOfDate(d:Date=null) {
  if (!d)
    d = new Date();
  var year = d.getUTCFullYear();
  var month = d.getUTCMonth();
  var day = d.getUTCDate();
  var hours = d.getUTCHours();
  var minutes = d.getUTCMinutes();
  var seconds = d.getUTCSeconds();
  var utcDate = new Date(year, month, day, hours, minutes, seconds);
  utcDate.setMinutes(utcDate.getMinutes() - 420);
  return utcDate
}

最好使用ISO 8601格式的日期时间。请查看使用 ISO-8601 日期格式的原因和好处。 https://www.iso.org/iso-8601-date-and-time-format.html

完整的 post 在这里 Implementing ISO 8601 date time format in Angular

ISO 8601 can be used by anyone who wants to use a standardized way of presenting:

Date,
Time of day,
Coordinated Universal Time (UTC),
Date and time,
Time intervals,
Recurring time intervals

您可以使用此代码以您想要的方式使用格式。希望对您有所帮助。

export interface HashTable<T> {
  [key: string]: T;
}
import { Injectable } from '@angular/core';
import { HashTable } from './hash-table';

type FormatFunc = (date: Date) => string;
@Injectable({
  providedIn: 'root'
})
export class DateFormat {
  formattingTokenFunc: HashTable<FormatFunc> = {};

  private formattingTokens = /(HH?|HH?|hh?|mm?|ss?|MM?|dd?|yy?y?y?|.)/g;

  constructor() {
    // add years function
    const getYearFunc = (date: Date) => date.getFullYear().toString();

    // Year, no leading zero (e.g. 2015 would be 15)
    this.addFormatToken('y', 0, (date: Date) =>
      (date.getFullYear() % 100).toString()
    );
    this.addFormatToken('yyy', 0, getYearFunc);
    this.addFormatToken('yyyy', 0, getYearFunc);
    // Year, leading zero (e.g. 2015 would be 015)
    this.addFormatToken('yy', 3, (date: Date) =>
      (date.getFullYear() % 100).toString()
    );

    // add months function
    const getMonthFunc = (date: Date) => (date.getMonth() + 1).toString();

    this.addFormatToken('M', 0, getMonthFunc);
    this.addFormatToken('MM', 2, getMonthFunc);

    // add day function
    const getDayFunc = (date: Date) => date.getDate().toString();

    this.addFormatToken('d', 0, getDayFunc);
    this.addFormatToken('dd', 2, getDayFunc);

    // add hours function
    const get12HrFunc = (date: Date) => (date.getHours() % 12).toString();

    // 12-hour clock, with a leading 0 eg (e.g. 06)
    this.addFormatToken('hh', 2, get12HrFunc);
    // 12-hour clock hour
    this.addFormatToken('h', 0, get12HrFunc);

    const get24HrFunc = (date: Date) => date.getHours().toString();

    this.addFormatToken('HH', 2, get24HrFunc);
    this.addFormatToken('H', 0, get24HrFunc);

    // add minute function
    const getMinFunc = (date: Date) => date.getMinutes().toString();
    this.addFormatToken('m', 0, getMinFunc);
    // Minutes with a leading zero
    this.addFormatToken('mm', 2, getMinFunc);

    // add seconds function
    const getSecFunc = (date: Date) => date.getSeconds().toString();
    this.addFormatToken('s', 0, getSecFunc);
    this.addFormatToken('ss', 2, getSecFunc);
  }

  formatToISO8601Date(date: Date | string): string {
    return this.format(date, 'yyyy-MM-dd');
  }

  format(date: Date | string, format: string): string {
    const finalDate = date instanceof Date ? date : new Date(date);

    const matches = format.match(this.formattingTokens);
    let result = '';

    matches.forEach(match => {
      // const hasFunc = this.formattingTokenFunc.hasOwnProperty('match');
      const formatFunc = this.formattingTokenFunc[match];

      result += formatFunc ? formatFunc(finalDate) : match;
    });

    return result;
  }

  prefixZero(length: number, input: string): string {
    return `${Math.pow(10, length)}${input}`.slice(-1 * length);
  }

  prefixZeroFunc(length: number, formatFunc: FormatFunc): FormatFunc {
    return (c: Date) => this.prefixZero(length, formatFunc(c));
  }

  private addFormatToken(
    token: string,
    addZeroesLength: number,
    // formatFunc: ((date: Date) => string)
    formatFunc: FormatFunc
  ): void {
    this.formattingTokenFunc[token] =
      addZeroesLength > 0
        ? this.prefixZeroFunc(addZeroesLength, formatFunc)
        : formatFunc;
  }
}