这是我的一点JS代码,这是需要的:

var secDiff = Math.abs(Math.round((utc_date-this.premiere_date)/1000));
this.years = this.calculateUnit(secDiff,(86400*365));
this.days = this.calculateUnit(secDiff-(this.years*(86400*365)),86400);
this.hours = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)),3600);
this.minutes = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)-(this.hours*3600)),60);
this.seconds = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)-(this.hours*3600)-(this.minutes*60)),1);

我想在“前”得到日期时间,但如果DST正在使用,那么日期是1小时。我不知道如何检查夏令时是否有效。

我怎样才能知道夏令时何时开始和结束?


当前回答

https://date-fns.org/v2.22.1/docs/Time-Zones可以用一行来解决

新日期()getUTCHours() + gettimezoneset(‘欧洲/阿姆斯特丹’)/ 1000 / 60;

其他回答

这个答案与公认的答案非常相似,但没有覆盖Date原型,并且只使用一个函数调用来检查日光节约时间是否有效,而不是两个。


这个想法是,由于没有国家遵守持续7个月的夏时制[1],在遵守夏时制的地区,1月份与UTC时间的偏移量将与7月份的偏移量不同。

虽然夏令时将时钟向前移动,但JavaScript总是在标准时间期间返回更大的值。因此,在1月和7月之间获取最小偏移量将获得夏令时期间的时区偏移量。

然后检查dates timezone是否等于该最小值。如果是,那么我们就是在夏令时;否则我们就不是了。

下面的函数使用这个算法。它接受一个日期对象d,如果夏令时在该日期有效,则返回true,如果不是则返回false:

function isDST(d) {
    let jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset();
    let jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset();
    return Math.max(jan, jul) !== d.getTimezoneOffset();    
}

你很接近了,但是有点差。你永远不需要计算你自己的时间,因为它是你自己的时钟的结果。它可以检测您是否在您的位置使用日光节约时间,但不能检测由偏移量产生的远程位置:

newDateWithOffset = new Date(utc + (3600000*(offset)));

This will still be wrong and off an hour if they are in DST. You need for a remote time account if they are currently inside their DST or not and adjust accordingly. try calculating this and change your clock to - lets say 2/1/2015 and reset the clock back an hour as if outside DST. Then calculate for an offset for a place that should still be 2 hours behind. It will show an hour ahead of the two hour window. You would still need to account for the hour and adjust. I did it for NY and Denver and always go the incorrect (hour ahead) in Denver.

面向未来的解决方案,适用于所有时区

设x为在不考虑夏时制的情况下进入利息年的预期毫秒数。 设y为从感兴趣日期的年份开始到Epoch的毫秒数。 设z为自感兴趣的完整日期和时间的Epoch以来的毫秒数 设t是z减去x和y: z - y - x。这就得到了由于夏令时而产生的偏移量。 如果t为零,则DST不生效。如果t不为零,则DST生效。

"use strict"; function dstOffsetAtDate(dateInput) { var fullYear = dateInput.getFullYear()|0; // "Leap Years are any year that can be exactly divided by 4 (2012, 2016, etc) // except if it can be exactly divided by 100, then it isn't (2100,2200,etc) // except if it can be exactly divided by 400, then it is (2000, 2400)" // (https://www.mathsisfun.com/leap-years.html). var isLeapYear = ((fullYear & 3) | (fullYear/100 & 3)) === 0 ? 1 : 0; // (fullYear & 3) = (fullYear % 4), but faster //Alternative:var isLeapYear=(new Date(currentYear,1,29,12)).getDate()===29?1:0 var fullMonth = dateInput.getMonth()|0; return ( // 1. We know what the time since the Epoch really is (+dateInput) // same as the dateInput.getTime() method // 2. We know what the time since the Epoch at the start of the year is - (+new Date(fullYear, 0)) // day defaults to 1 if not explicitly zeroed // 3. Now, subtract what we would expect the time to be if daylight savings // did not exist. This yields the time-offset due to daylight savings. - (( (( // Calculate the day of the year in the Gregorian calendar // The code below works based upon the facts of signed right shifts // • (x) >> n: shifts n and fills in the n highest bits with 0s // • (-x) >> n: shifts n and fills in the n highest bits with 1s // (This assumes that x is a positive integer) -1 + // first day in the year is day 1 (31 & ((-fullMonth) >> 4)) + // January // (-11)>>4 = -1 ((28 + isLeapYear) & ((1-fullMonth) >> 4)) + // February (31 & ((2-fullMonth) >> 4)) + // March (30 & ((3-fullMonth) >> 4)) + // April (31 & ((4-fullMonth) >> 4)) + // May (30 & ((5-fullMonth) >> 4)) + // June (31 & ((6-fullMonth) >> 4)) + // July (31 & ((7-fullMonth) >> 4)) + // August (30 & ((8-fullMonth) >> 4)) + // September (31 & ((9-fullMonth) >> 4)) + // October (30 & ((10-fullMonth) >> 4)) + // November // There are no months past December: the year rolls into the next. // Thus, fullMonth is 0-based, so it will never be 12 in Javascript (dateInput.getDate()|0) // get day of the month )&0xffff) * 24 * 60 // 24 hours in a day, 60 minutes in an hour + (dateInput.getHours()&0xff) * 60 // 60 minutes in an hour + (dateInput.getMinutes()&0xff) )|0) * 60 * 1000 // 60 seconds in a minute * 1000 milliseconds in a second - (dateInput.getSeconds()&0xff) * 1000 // 1000 milliseconds in a second - dateInput.getMilliseconds() ); } // Demonstration: var date = new Date(2100, 0, 1) for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0)) console.log(date.getMonth()+":\t"+dstOffsetAtDate(date)/60/60/1000+"h\t"+date); date = new Date(1900, 0, 1); for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0)) console.log(date.getMonth()+":\t"+dstOffsetAtDate(date)/60/60/1000+"h\t"+date); // Performance Benchmark: console.time("Speed of processing 16384 dates"); for (var i=0,month=date.getMonth()|0; i<16384; i=i+1|0) date.setMonth(month=month+1+(dstOffsetAtDate(date)|0)|0); console.timeEnd("Speed of processing 16384 dates");

我相信上面的代码片段优于这里发布的所有其他答案,原因有很多。

This answer works in all time zones, even Antarctica/Casey. Daylight savings is very much subject to change. It might be that 20 years from now, some country might have 3 DST periods instead of the normal 2. This code handles that case by returning the DST offset in milliseconds, not just whether DST is in effect or not in effect. The size of the months of the year and the way that Leap Years work fits perfectly into keeping our time on track with the sun. Heck, it works so perfectly that all we ever do is just adjust mere seconds here and there. Our current system of leap years has been in effect since February 24th, 1582, and will likely stay in effect for the foreseeable future. This code works in timezones that do not use DST. This code works in historic times before when DST was implemented (such as the 1900s). This code is maximally integer-optimized and should give you no problem if called in a tight loop. After running the code snippet above, scroll down to the bottom of the output to see the performance benchmark. My computer is able to process 16384 dates in 29ms on FireFox.

但是,如果您没有为超过2个DST周期做准备,那么可以使用下面的代码来确定DST是否作为布尔值有效。

function isDaylightSavingsInEffect(dateInput) {
    // To satisfy the original question
    return dstOffsetAtDate(dateInput) !== 0;
}

https://date-fns.org/v2.22.1/docs/Time-Zones可以用一行来解决

新日期()getUTCHours() + gettimezoneset(‘欧洲/阿姆斯特丹’)/ 1000 / 60;

我最近需要用UTC和DST创建一个日期字符串,根据Sheldon的回答,我把它放在一起:

Date.prototype.getTimezone = function(showDST) { var jan = new Date(this.getFullYear(), 0, 1); var jul = new Date(this.getFullYear(), 6, 1); var utcOffset = new Date().getTimezoneOffset() / 60 * -1; var dstOffset = (jan.getTimezoneOffset() - jul.getTimezoneOffset()) / 60; var utc = "UTC" + utcOffset.getSign() + (utcOffset * 100).preFixed(1000); var dst = "DST" + dstOffset.getSign() + (dstOffset * 100).preFixed(1000); if (showDST) { return utc + " (" + dst + ")"; } return utc; } Number.prototype.preFixed = function (preCeiling) { var num = parseInt(this, 10); if (preCeiling && num < preCeiling) { num = Math.abs(num); var numLength = num.toString().length; var preCeilingLength = preCeiling.toString().length; var preOffset = preCeilingLength - numLength; for (var i = 0; i < preOffset; i++) { num = "0" + num; } } return num; } Number.prototype.getSign = function () { var num = parseInt(this, 10); var sign = "+"; if (num < 0) { sign = "-"; } return sign; } document.body.innerHTML += new Date().getTimezone() + "<br>"; document.body.innerHTML += new Date().getTimezone(true); <p>Output for Turkey (UTC+0200) and currently in DST: &nbsp; UTC+0300 (DST+0100)</p> <hr>