我有一个网页,有三个下拉菜单,分别是日、月和年。如果我使用JavaScript Date构造函数接受数字,那么我得到一个Date对象为我的当前时区:

new Date(xiYear, xiMonth, xiDate)

给出正确的日期,但由于夏令时,它认为日期是GMT+01:00。

这里的问题是,然后我将这个日期传递给一个Ajax方法,当日期在服务器上被反序列化时,它已经转换为GMT,因此失去了一个小时,这将一天往回移动了一个小时。 现在我可以将日、月和年分别传递到Ajax方法中,但似乎应该有更好的方法。

接受的答案为我指明了正确的方向,但是仅仅使用setUTCHours()本身就改变了:

Apr 5th 00:00 GMT+01:00 

to

Apr 4th 23:00 GMT+01:00

然后,我还必须设置UTC日期、月份和年份

Apr 5th 01:00 GMT+01:00

这正是我想要的


当前回答

其实做起来一点也不难,但肯定不是凭直觉就能得出解决方案的。这里有一些非常复杂的答案(尽管也有一些不错的答案)。下面是我为确保我的服务器时间戳与我的本地时间戳匹配而提出的方法,无论我部署的服务器恰好位于哪个时区。

(CET =中欧时区,正好是我个人的时区;你可以得到任何给定时区的偏移量并计算它,如果你愿意,甚至可以把它作为一个参数,但对于我的目的,我只需要让我的日期都是所需的一致时区。)

    const convertDateToCET = function(date) {
        date = new Date(date)
        // let startTime = date.getTime();
        const cetOffset = -120; // this is the number you get from running 
        // `(new Date()).getTimezoneOffset()` if you're on a machine in CET
        const offsetFromCET = (date.getTimezoneOffset() - cetOffset);
        const cetMillsecondOffset = ( cetOffset* 60 * 1000);
        date = new Date( date.getTime() - cetMillsecondOffset ) 
        // let endTime = date.getTime()
        // console.log("updated date from",startTime,"to",endTime)
        return date;
    },

用这个短语,你可以按照你所期望的方式来定一个时间。

    let myDate = new Date("12-4-2021")
    myDate.setHour(14)
    myDate.setMinute(30)
    // now myDate is 2:30pm, December 4th, 2021, in whatever the timezone the machine of code running happens to be in
    myDate = convertDateToCET(myDate)
    // now myDate will show up as 2:30pm, Dec 4th, 2021, mapped into your local timezone
    // so, if you're in the UK, and one hour behind CET, myDate is now 1:30pm, Dec 4th, 2021

这里的关键是date.getTimezoneOffset()。如果你参加了四六级考试,那么这个数字就是-120,这样就消去了,没有区别(所以四六级考试的结果就是四六级考试的结果)。如果你在英国,比CET晚一小时,那么输出将是-60,这意味着-60 + 120 = +60,这导致我们将输入时间改变一小时,以此类推。

对于这种情况,转换所有内容并使用UTC可能更有意义,但考虑到我的所有输入时间都是使用CET,而且我最初是根据机器上的本地情况开发系统的,因此这个实用程序允许我通过在几个关键位置调用这个函数来转换现有代码。

注意:请确保不要在同一日期多次应用此函数调用,因为您将多次重新应用偏移量,将其抛出!

其他回答

您可以使用库来帮助更改时区

moment-timezone

var moment = require("moment-timezone");
const today = new Date();
var timeGet = moment(today);
timeGet.tz("Asia/Karachi").format("ha z");

这可以改变您所在地区的时区,粘贴您所在地区的区域,并获得真正的gmt+解决问题

欲了解更多详细信息,请访问moment timezone官方文档

GMT -03:00示例

new Date(new Date()-3600*1000*3).toISOString();  // 2020-02-27T15:03:26.261Z

甚至

now  = new Date().getTime()-3600*1000*3; // 1582818380528
data = new Date(now).toISOString();      // 2020-02-27T15:03:26.261Z

我不相信这是可能的-没有能力设置一个日期对象的时区后,它被创建。

在某种程度上,这是有道理的——在概念上(如果不是在实施中);per http://en.wikipedia.org/wiki/Unix_timestamp(强调我):

Unix时间,或POSIX时间,是一种描述时间瞬间的系统,定义为自1970年1月1日星期四午夜协调世界时(UTC)以来经过的秒数。

一旦你构建了一个,它将代表“真实”时间中的某个点。只有当您希望将抽象时间点转换为人类可读的字符串时,时区才有意义。

因此,只能更改Date在构造函数中表示的实际时间是有道理的。遗憾的是,似乎没有办法传递一个显式的时区-你正在调用的构造函数(可以说是正确的)将你的“本地”时间变量转换为GMT时,它正常存储它们-所以没有办法使用int, int, int构造函数为GMT时间。

从好的方面来说,只使用接受String的构造函数是很简单的。您甚至不需要将数字月份转换为字符串(至少在Firefox上),所以我希望一个简单的实现可以工作。然而,在尝试之后,它在Firefox、Chrome和Opera中成功工作,但在Konqueror(“无效日期”)、Safari(“无效日期”)和IE(“NaN”)中失败。我猜你只需要一个查找数组来将月份转换为字符串,就像这样:

var months = [ '', 'January', 'February', ..., 'December'];

function createGMTDate(xiYear, xiMonth, xiDate) {
   return new Date(months[xiMonth] + ' ' + xiDate + ', ' + xiYear + ' 00:00:00 GMT');
}

使用. settutchours()可以实际设置utc时间的日期,这将允许您在整个系统中使用utc时间。

但是不能在构造函数中使用UTC设置它,除非指定日期字符串。

使用新的日期(日期。UTC(年,月,日,小时,分,秒)),您可以从特定的UTC时间创建一个日期对象。

如果要检查两个日期之间的时间差异,只需检查第二个时区是否比第一个所需时区小或大,然后减去或增加一个时间。

  const currTimezone = new Date().getTimezoneOffset(); // your timezone
  const newDateTimezone = date.getTimezoneOffset(); // date with unknown timezone

  if (currTimezone !== newDateTimezone) {
    // and below you are checking if difference should be - or +. It depends on if unknown timezone is lesser or greater than yours
    const newTimezone = (currTimezone - newDateTimezone) * (currTimezone > newDateTimezone ? 1 : -1);
    date.setTime(date.getTime() + (newTimezone * 60 * 1000));
  }