如何使用 JavaScript 从 1 - 366 计算一年中的哪一天?
例如:
January 3
应该是3
。February 1
应该是32
。
如何使用 JavaScript 从 1 - 366 计算一年中的哪一天?
例如:
January 3
应该是3
。February 1
应该是32
。按照 OP 的编辑:
var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = now - start;
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);
编辑:上面的代码会失败时,now
是3月26日和10月29日之间的日期now
的时间是凌晨1点之前(如0时59分59秒)。这是因为代码没有考虑夏令时。您应该对此进行补偿:
var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = (now - start) + ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);
这适用于所有国家/地区的夏令时更改(上面的“中午”在澳大利亚不起作用):
Date.prototype.isLeapYear = function() {
var year = this.getFullYear();
if((year & 3) != 0) return false;
return ((year % 100) != 0 || (year % 400) == 0);
};
// Get Day of Year
Date.prototype.getDOY = function() {
var dayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
var mn = this.getMonth();
var dn = this.getDate();
var dayOfYear = dayCount[mn] + dn;
if(mn > 1 && this.isLeapYear()) dayOfYear++;
return dayOfYear;
};
我觉得很有趣,没有人考虑使用 UTC,因为它不受 DST 的约束。因此,我提出以下建议:
function daysIntoYear(date){
return (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000;
}
您可以使用以下方法对其进行测试:
[new Date(2016,0,1), new Date(2016,1,1), new Date(2016,2,1), new Date(2016,5,1), new Date(2016,11,31)]
.forEach(d =>
console.log(`${d.toLocaleDateString()} is ${daysIntoYear(d)} days into the year`));
2016 年闰年的输出(使用http://www.epochconverter.com/days/2016验证):
1/1/2016 is 1 days into the year
2/1/2016 is 32 days into the year
3/1/2016 is 61 days into the year
6/1/2016 is 153 days into the year
12/31/2016 is 366 days into the year
Date.prototype.dayOfYear= function(){
var j1= new Date(this);
j1.setMonth(0, 0);
return Math.round((this-j1)/8.64e7);
}
alert(new Date().dayOfYear())
幸运的是,如果数量这个问题没有指定当前需要一天,留有余地这个答案。
还有一些答案(也在其他问题上)有闰年问题或使用了日期对象。尽管 javascriptDate object
涵盖了 1970 年 1 月 1 日左右的大约 285616 年(100,000,000 天),但我已经受够了不同浏览器(最显着的是 0 到 99 年)的各种意外日期不一致。我也很好奇如何计算。
所以我写了一个简单且最重要的小算法来计算正确的(Proleptic Gregorian / Astronomical / ISO 8601:2004 (clause 4.3.2.1),所以年份0
存在并且是闰年并且支持负年)一年中的某一天基于年、月和日。
请注意,在AD/BC
符号中,公元 0 年不存在:相反,年份1 BC
是闰年!如果您需要考虑 BC 表示法,那么只需先减去(否则为正)年份值的一年!!
我修改了(对于javascript)短路位掩码模leapYear算法并提出了一个幻数来按位查找偏移量(不包括jan和feb,因此需要10 * 3位(30位小于31 位,所以我们可以安全地在位移位上保存另一个字符而不是>>>
))。
请注意,月或日都不能是0
。这意味着,如果你需要这个公式只为当前日期(用喂养它.getMonth()
),你只需要删除--
的--m
。
请注意,这假定一个有效的日期(尽管错误检查只是更多的字符)。
function dayNo(y,m,d){
return --m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>
<br><hr><br>
<button onclick="
var d=new Date();
this.nextSibling.innerHTML=dayNo(d.getFullYear(), d.getMonth()+1, d.getDate()) + ' Day(s)';
">get current dayno:</button><span></span>
这是具有正确范围验证的版本。
function dayNo(y,m,d){
return --m>=0 && m<12 && d>0 && d<29+(
4*(y=y&3||!(y%25)&&y&15?0:1)+15662003>>m*2&3
) && m*31-(m>1?(1054267675>>m*3-6&7)-y:0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>
同样,一行,但我将其分成 3 行以提高可读性(以及以下解释)。
最后一行与上面的函数相同,但是(相同的)leapYear 算法移到了前面的短路部分(在天数计算之前),因为它还需要知道一个月有多少天给定(闰)年。
中间一行使用另一个幻数计算给定(闰)年中给定月份的正确偏移量(最大天数):因为31-28=3
和3
只是 2 位,那么12*2=24
位,我们可以存储所有 12 个月。由于加法比减法更快,我们添加偏移量(而不是从 中减去31
)。为了避免 2 月份出现闰年决策分支,我们动态修改了这个神奇的查找数。
这给我们留下了(非常明显的)第一行:它检查月份和日期是否在有效范围内,并确保我们false
在范围错误时返回值(注意这个函数也不应该能够返回 0,因为 1 jan 0000仍然是第 1 天。),提供简单的错误检查:if(r=dayNo(/*y, m, d*/)){}
。
如果以这种方式使用(月和日可能不是0
),则可以更改--m>=0 && m<12
为m>0 && --m<12
(保存另一个字符)。
我以当前形式输入代码段的原因是,对于基于 0 的月份值,只需--
要从--m
.
额外:
请注意,如果您只需要每月最大天数,请不要使用这一天的每月算法。在那种情况下,有一个更有效的算法(因为我们只需要 leepYear 当月份是二月时)我发布作为回答这个问题:使用 javascript 确定一个月中天数的最佳方法是什么?.