这是我需要的一些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小时。我不知道如何检查DST是否正在使用。
如何知道夏令时的开始和结束时间?
答案 0 :(得分:274)
此代码使用getTimezoneOffset
在标准时间与夏令时(DST)期间返回更大值的事实。因此,它确定标准时间内的预期输出,并比较给定日期的输出是否相同(标准)或更低(DST)。
请注意,getTimezoneOffset
会返回UTC的 west 区域的正分钟数,通常表示为负小时(因为他们“落后”UTC)。例如,洛杉矶 UTC-8h 标准, UTC-7h DST。 getTimezoneOffset
在12月(冬季,标准时间)返回480
(正480分钟),而不是-480
。它返回东半球的负数字(冬季为-600
,尽管这是“领先”( UTC + 10h )。
Date.prototype.stdTimezoneOffset = function () {
var jan = new Date(this.getFullYear(), 0, 1);
var jul = new Date(this.getFullYear(), 6, 1);
return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
}
Date.prototype.isDstObserved = function () {
return this.getTimezoneOffset() < this.stdTimezoneOffset();
}
var today = new Date();
if (today.isDstObserved()) {
alert ("Daylight saving time!");
}
答案 1 :(得分:19)
创建两个日期:一个在六月,一个在一月。比较它们的getTimezoneOffset()值。
现在检查当前日期的getTimezoneOffset()。
答案 2 :(得分:12)
今天我遇到了同样的问题,但由于我们的夏令时在美国不同的时间开始和停止(至少从我的理解),我使用的路线略有不同......
var arr = [];
for (var i = 0; i < 365; i++) {
var d = new Date();
d.setDate(i);
newoffset = d.getTimezoneOffset();
arr.push(newoffset);
}
DST = Math.min.apply(null, arr);
nonDST = Math.max.apply(null, arr);
然后,您只需将当前时区偏移与DST和nonDST进行比较,以查看哪一个匹配。
答案 3 :(得分:9)
基于Matt Johanson对Sheldon Griffin提供的解决方案的评论,我创建了以下代码:
Date.prototype.stdTimezoneOffset = function() {
var fy=this.getFullYear();
if (!Date.prototype.stdTimezoneOffset.cache.hasOwnProperty(fy)) {
var maxOffset = new Date(fy, 0, 1).getTimezoneOffset();
var monthsTestOrder=[6,7,5,8,4,9,3,10,2,11,1];
for(var mi=0;mi<12;mi++) {
var offset=new Date(fy, monthsTestOrder[mi], 1).getTimezoneOffset();
if (offset!=maxOffset) {
maxOffset=Math.max(maxOffset,offset);
break;
}
}
Date.prototype.stdTimezoneOffset.cache[fy]=maxOffset;
}
return Date.prototype.stdTimezoneOffset.cache[fy];
};
Date.prototype.stdTimezoneOffset.cache={};
Date.prototype.isDST = function() {
return this.getTimezoneOffset() < this.stdTimezoneOffset();
};
考虑到所有评论和之前建议的答案,特别是它,它试图充分利用所有世界:
1)缓存每年stdTimezoneOffset的结果,这样您就不需要在同一年测试多个日期时重新计算它。
2)它不假设DST(如果它存在的话)必然在7月, 并且即使它会在某个时刻和某个地方出现在任何月份也能工作。 然而,在性能方面,如果确实是7月(或接近几个月)确实是DST,它将更快地工作。
3)更糟糕的情况是它将比较每月第一天的getTimezoneOffset。 [并且每年测试一次]。
它仍然做出的假设是,如果有DST期间大于一个月。
如果有人想要删除这个假设,他可以将循环变成更像Aaron Cole提供的解决方案中的东西 - 但我仍然会提前半年跳出来并在发现两个不同的偏移时突破循环] < / p>
答案 4 :(得分:8)
这个答案与接受的答案非常相似,但并没有覆盖Date
原型,只使用一个函数调用来检查夏令时是否有效,而不是两个。
这个想法是,因为没有国家观察持续7个月
虽然夏令时将时钟向前移动,但JavaScript在标准时间内始终返回更大值。因此,在1月到7月之间获得最小偏移将在夏令时期间获得时区偏移。
然后我们检查日期时区是否等于该最小值。如果是,那么我们在DST;否则我们不是。
以下函数使用此算法。它需要一个日期对象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();
}
答案 5 :(得分:4)
moment.js库在其时间对象上提供.isDst()
方法。
时刻#isDST检查当前时刻是否为夏令时。
moment([2011, 2, 12]).isDST(); // false, March 12 2011 is not DST
moment([2011, 2, 14]).isDST(); // true, March 14 2011 is DST
答案 6 :(得分:2)
使用Moment.js(https://momentjs.com/)
如果观察到日光节约, moment().isDST();
将为您提供帮助。
它还具有帮助功能,可以为您计算相对时间。您不需要手动计算
例如moment("20200105", "YYYYMMDD").fromNow();
答案 7 :(得分:1)
你的关闭但稍微关闭了。您永远不需要计算自己的时间,因为它是您自己的时钟的结果。它可以检测您是否在您所在的位置使用夏令时,但不能检测偏移产生的远程位置:
newDateWithOffset = new Date(utc + (3600000*(offset)));
如果它们在DST中,这仍然是错误的,并且会在一小时后停止。如果他们当前在DST内部,您需要一个远程时间账户并进行相应调整。尝试计算这个并将时钟更改为 - 比如说2015年2月1日并将时钟重新设置为一小时,就像在夏令时之外一样。然后计算一个应该仍然落后2小时的地方的偏移量。它将显示两小时窗口前一小时。您仍然需要考虑小时并进行调整。我是为纽约和丹佛做过的,并且在丹佛总是走错了(提前一小时)。
答案 8 :(得分:1)
我发现使用Moment.js库以及此处描述的一些概念(比较1月到6月)效果非常好。
这个简单的函数将返回用户所在的时区是否遵守夏令时:
function HasDST() {
return moment([2017, 1, 1]).isDST() != moment([2017, 6, 1]).isDST();
}
检查此功能(在Windows上)的一种简单方法是将您的时区更改为非DST区域,例如Arizona将返回false,而EST或PST将返回true。
答案 9 :(得分:1)
JavaScript中的getTimezoneOffset()
方法在浏览器中返回偏离00:00时区的分钟数。例如,夏令时(DST)中的America / New_York时区返回数字300. 300分钟与零相差5小时。 300分钟除以60分钟是5小时。每个时区都与零时区进行比较,+ 00:00 / Etc / GMT /格林威治时间。
接下来你必须知道的是,偏移量与实际时区的符号相反。
有关时区的信息由互联网号码分配机构(iana)维护
时区的格式很好的表格由joda.org提供
+00:00或Etc / GMT是格林威治时间
所有时区都偏离+00:00 /“Etc / GMT”/格林威治时间
夏令时总是比夏天的“常规”时间更早。你在秋季重新设置时钟。 (“后退”口号记住该怎么做)
因此,美国/纽约时间夏令时(冬季)是常规时间前一小时。所以,例如,通常是下午5点。夏天下午在纽约市,现在下午4点。美国/纽约时间夏令时。名称“America / New_York”时间是“长格式”时区名称。美国东海岸通常将其时区称为东部标准时间(EST)
如果您想将今天的时区偏移与某个其他日期的时区偏移进行比较,您需要知道时区偏移的数学符号(+/-“正/负”)与时间相反区。
查看joda.org上的时区表,找到“America / New_York”的时区。标准偏移前面会有一个负号。
地球在其轴上逆时针旋转。一个人在格林威治观看日出,在纽约市有人看到日出前5小时看日出。在美国东海岸有人看到日出之后,美国西海岸的某个人会看到日出。
你需要了解所有这一切的原因。这样您就可以在逻辑上确定某些JavaScript代码是否正确获取DST状态,而无需在一年中的不同时间测试每个时区。
想象一下,11月在纽约市,时钟已经缩短了一个小时。在纽约市的夏天,抵消时间为240分钟或4小时。
您可以通过创建7月份的日期然后获取偏移量来测试。
var July_Date = new Date(2017, 6, 1);
var july_Timezone_OffSet = July_Date.getTimezoneOffset();
console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)
什么将打印到浏览器的开发人员工具控制台日志?
答案是:240
因此,现在您可以在1月创建一个日期,并查看您的浏览器返回的冬季时区偏移量。
var Jan_Date = new Date(2017, 0, 1);//Month is zero indexed - Jan is zero
var jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();
console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)
答案是:300
显然300大于240.那么,这意味着什么?您是否应该编写测试冬季偏移量大于夏季偏移量的代码?或者夏季偏移小于冬季抵消?如果夏季和冬季时区偏移之间存在差异,则可以假设DST正用于此时区。但是,这并不能告诉您 今天 是否在浏览器时区使用DST。所以,你需要获得今天的时区偏移量。
var today = new Date();
var todaysTimeZone = today.getTimezoneOffset();
console.log('todaysTimeZone : ' + todaysTimeZone)
答案是:? - 取决于一年中的时间
如果今天的时区偏移和夏季时区偏移相同,则 AND 夏季和冬季时区偏移量不同,那么通过逻辑演绎,今天必须不是夏令时。< / p>
您可以省略比较夏季和冬季时区偏移,(知道DST是否用于此时区),只是将今天的时区偏移与夏季TZ偏移进行比较,并始终得到正确的答案?
today's TZ Offset !== Summer TZ Offset
嗯,今天是冬天还是夏天?如果你知道那么你可以应用以下逻辑:
if ( it_is_winter && ( todays_TZ_Offset !== summer_TZ_Offset) {
var are_We_In_DST = true;
}
但问题是,你不知道今天的日期是冬天还是夏天。 DST开始和停止时,每个时区都有自己的规则。您需要跟踪世界上每个时区的每个时区规则。所以,如果有更好更简单的方法,那么你也可以采用更好更简单的方式。
我们还剩下的是,您需要知道此时区是否使用夏令时,然后将今天的时区偏移与夏令时偏移进行比较。这总能给你一个可靠的答案。
最终的逻辑是:
if ( DST_Is_Used_In_This_Time_Zone && ( todays_TZ_Offset !== summer_TZ_Offset) {
var are_We_In_DST = true;
}
确定浏览器中的时区是否使用夏令时的功能:
function is_DST_Used_In_This_TimeZone() {
var Jan_Date, jan_Timezone_OffSet, July_Date, july_Timezone_OffSet
offsetsNotEqual, thisYear, today;
today = new Date();//Create a date object that is now
thisYear = today.getFullYear();//Get the year as a number
Jan_Date = new Date(thisYear, 0, 1);//Month is zero indexed - Jan is zero
jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();
console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)
July_Date = new Date(thisYear, 6, 1);
july_Timezone_OffSet = July_Date.getTimezoneOffset();
console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)
offsetsNotEqual = july_Timezone_OffSet !== jan_Timezone_OffSet;//True if not equal
console.log('offsetsNotEqual: ' + offsetsNotEqual);
return offsetsNotEqual;//If the offsets are not equal for summer and
//winter then the only possible reason is that DST is used for
//this time zone
}
答案 10 :(得分:0)
我最近需要使用UTC和DST创建一个日期字符串,并根据谢尔顿的回答我把它放在一起:
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);
&#13;
<p>Output for Turkey (UTC+0200) and currently in DST: UTC+0300 (DST+0100)</p>
<hr>
&#13;
答案 11 :(得分:0)
x
设为感兴趣年份的预期毫秒数,而不考虑夏令时。y
设为自感兴趣日期之年开始的Epoch以来的毫秒数。z
为自感兴趣的完整日期和时间Epoch起的毫秒数t
与x
中的y
和z
减:z - y - x
。由于DST,这将产生偏移。 t
为零,则DST无效。如果t
不为零,则DST有效。
(function(){"use strict";
function isDaylightSavingsInEffect(dateInput) {
return dstOffsetAtDate(dateInput) !== 0;
}
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, 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)
(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");
})();
由于许多原因,我认为上述代码段优于此处发布的所有其他答案。
答案 12 :(得分:0)
使用Date.toString().indexOf('Daylight Time') > -1
"" + new Date()
1000年1月1日星期六GMT-0500(东部标准时间)
"" + new Date(...)
星期日,五月01 100033 00:00:00 GMT-0400(东部时间白天时间)
这似乎与所有浏览器兼容。
答案 13 :(得分:0)
ES6样式
- set_fact:
my_list: "{{ my_dict|dict2list }}"
答案 14 :(得分:0)
更新:
在尝试在自定义 datetime
选择器中使用这些函数后,我注意到从 3 月切换到 4 月会按预期切换时区,因为我的时区在 3 月切换 DST。出乎意料的是,它正在切换到下一个时区,而不是在同一时区的标准和日光之间切换。
事实证明这是因为我的原始函数总是为当前时间或过去的任意固定时间创建 new Date()
。将其与 3 月和 4 月的相对时间进行比较意味着它会在逻辑上将 DST 切换检测为切换时区。
解决方案是将相对时间传递给效用函数,所以我所有的比较都是针对相对时间,而不是现在或任意固定时间。失去了一些紧凑性,但现在逻辑可以根据需要工作。
工作流程更新:
t
参数默认为 new Date()
Date
null
或不传入std()
更新为使用 t.setMonth(v);
更改固定时间的月份
.getTimezoneOffset()
不能链接到 .setMonth()
,因此我们需要从一行表示法切换到使用闭包 ({}
)、终止符 (;
) 和 {{ 1}}return
示例循环遍历每个月(console.log()
到 0
)
11
) 克隆固定日期对象let ts = +t;
类型之前的 +
将其转换为带有 Unix 时间戳的 Date
number
也接受 Unix 时间戳来创建固定时间Date()
对象,月份设置为 Date
,这违背了目的6
扩展来自@nkitku 的紧凑而神秘的解决方案,将其变成一组可重用的功能。
工作流程:
let ns = {
std: (t = new Date()) => Math.max(...[0, 6].map(v => {
t.setMonth(v);
return t.getTimezoneOffset();
})),
is_dst: (t = new Date()) => t.getTimezoneOffset() < ns.std(t),
utc: (t, std = 0) => {
t = t || new Date();
let z = std ? ns.std(t) : t.getTimezoneOffset(),
zm = z % 60;
return 'UTC' + (z > 0 ? '-' : '+') + (z / 60) + (zm ? ':' + zm : '');
}
};
//current time only
console.log(ns.std(), ns.is_dst(), ns.utc(), ns.utc(null, 1));
//iterate each month
let t = new Date(2021,0,1);
for (let i = 0; i < 12; i++) {
t.setMonth(i);
let ts = +t;
console.log(t.toDateString().split(" ")[1], ns.std(new Date(ts)), ns.is_dst(new Date(ts)), ns.utc(new Date(ts)), ns.utc(new Date(ts), 1));
}
范围内,因此它们不会与代码中可能具有相同名称的其他函数发生冲突
ns
相当于 std: ()=>Math.max(),
function std(){ return Math.max(); }
返回标准时间的时区偏移量std()
设置没有 DST 的月份和有 DST 的月份的比较
[0, 6]
为一月,因为 0
是零索引的Date.setMonth()
七月6
将月份的 ...[]
转换为 Array
,因此我们可以应用 Set
函数
map()
map()
在同一个函数上运行一组变量并返回结果数组map()
对象
Date
)是任意的,因为年份对于此计算并不重要95
作为变量 [0, 6]
v
)也是任意的1
,然后创建一个 new Date()
,但使用任意数字更紧凑、更快.setMonth(v)
返回每个月的偏移量并将它们推送到结果数组getTimezoneOffset()
从结果中找出最大值,即标准时间偏移Math.max()
检查当前是否为夏令时
is_dst()
获取当前偏移量,带或不带 DSTnew Date().getTimezoneOffset()
获取标准时间的偏移量ns.std()
返回 UTC 表示法的字符串
utc()
参数默认为关闭std
根据标志将时间设置为夏令时或标准z = std ? ns.std() : new Date().getTimezoneOffset()
捕获分钟,因为某些区域例如使用 30 分钟zm = z % 60
为每个 UTC 符号分配正确的符号;正偏移值在符号中显示为负偏移(z > 0 ? '-' : '+')
根据表示法以一位数格式捕获小时数,因此无需 (z / 60)
)` 获取两位数格式.toString().padStart(2,'0
附加时区的分钟数由于此版本旨在紧凑,因此您可以通过去除多余的空白来节省更多空间。虽然这确实是一个压缩器的工作。
(zm ? ':' + zm : '')
std:()=>Math.max(...[0,6].map(v=>new Date(95,v,1).getTimezoneOffset())),
答案 15 :(得分:0)
用https://date-fns.org/v2.22.1/docs/Time-Zones一行就可以解决
new Date().getUTCHours() + getTimezoneOffset('欧洲/阿姆斯特丹') / 1000 / 60 / 60;