如何使用javascript计算一年中的某一天,从1到366?例如:
答案 0 :(得分:106)
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日之间的日期时will fail上方的代码,而now
的时间是凌晨1点(例如00:59:59)。这是因为代码没有考虑夏令时。你应该compensate:
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);
答案 1 :(得分:46)
这适用于所有国家/地区的夏令时变化("中午和#34;以上一个在澳大利亚不起作用):
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;
};
答案 2 :(得分:17)
Date.prototype.dayOfYear= function(){
var j1= new Date(this);
j1.setMonth(0, 0);
return Math.round((this-j1)/8.64e7);
}
alert(new Date().dayOfYear())
答案 3 :(得分:9)
幸运的是,这个问题没有说明是否需要当前天的数量,为这个答案留出了空间。
还有一些答案(也在其他问题上)有闰年问题或使用Date-object。虽然javascript的Date object
涵盖了1970年1月1日左右的大约285616年(100,000,000天),但我厌倦了不同浏览器中的各种意外日期inconsistencies(最明显的是0到99年)。我也很好奇如何计算它。
所以我写了一个简单的,最重要的,小算法来计算正确(Proleptic Gregorian / Astronomical / ISO 8601:2004 (第4.3.2.1条),因此基于年,,year 0
存在,并且是闰年,并且负年被支持)。月和天
请注意,在AD/BC
表示法中,年份0 AD / BC不存在:相反年份1 BC
是闰年!如果您需要考虑BC符号,那么只需先减去一年(否则为正)年值!!
我修改了(对于javascript)short-circuit bitmask-modulo leapYear algorithm并提出了一个神奇的数字来执行偏移的逐位查找(不包括jan和feb,因此需要10 * 3位(30位小于31位,因此我们可以安全地在bitshift上保存另一个字符,而不是>>>
)。
请注意,月份或日期均不得为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
和{{ 1}}只是2位,然后是3
位,我们可以存储所有12个月。由于加法可以比减法更快,我们添加偏移量(而不是从12*2=24
中减去它)。为避免2月份的闰年决策分支,我们会动态修改该魔术查找号码。
这给我们留下了(非常明显的)第一行:它检查月份和日期是否在有效范围内,并确保我们在范围错误上有 31
返回值(请注意此函数也不应该返回0,因为1 jan 0000仍然是第1天。),提供简单的错误检查:false
。
如果以这种方式使用(月份和日期可能不是if(r=dayNo(/*y, m, d*/)){}
),则可以将0
更改为--m>=0 && m<12
(保存另一个字符)。
我在其当前表单中输入代码段的原因是,对于基于0的月份值,只需从m>0 && --m<12
中删除--
。
额外:
注意,如果您只需要每月最多一天,请不要使用这一天的每月算法。在这种情况下,有一个更有效的算法(因为当月份是2月时我们只需要leepYear)我发布了回答这个问题:What is the best way to determine the number of days in a month with javascript?。
答案 4 :(得分:4)
这是一种查找当年当天的简单方法,它应该说明闰年没有问题:
<强>使用Javascript:强>
Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);
Google Apps脚本中的Javascript:
Math.round((new Date().setHours(23) - new Date(new Date().getYear(), 0, 1, 0, 0, 0))/1000/60/60/24);
此代码的主要操作是查找当前年份中已经过的毫秒数,然后将此数字转换为天数。通过减去当前年度第一天的第一秒的毫秒数,可以找到当前年份已经过的毫秒数,这是通过new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0)
(Javascript)或{{1}获得的(Google Apps脚本),从当天的第23个小时的毫秒开始,与new Date(new Date().getYear(), 0, 1, 0, 0, 0)
一起找到。将当前日期设置为第23小时的目的是确保new Date().setHours(23)
正确舍入年中的某一天。
一旦你有当前年份的毫秒数,那么你可以将这个时间换成天数,除以1000,将毫秒转换为秒,然后除以60,将秒转换为分钟,然后除以60转换为分钟到小时,最后除以24,将小时数转换为几天。
注意:此帖子经过编辑,以说明Google Apps脚本中实现的JavaScript和JavaScript之间的差异。此外,还为答案添加了更多上下文。
答案 5 :(得分:4)
好吧,如果我理解正确的话,你想要闰年366,否则365,对吗?一年是闰年,如果它可以被4整除,但不会被100整除,除非它可以被400整除:
function daysInYear(year) {
if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
// Leap year
return 366;
} else {
// Not a leap year
return 365;
}
}
在这种情况下,我不认为这是一种内置方法;你需要这样做:
function daysInFebruary(year) {
if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
// Leap year
return 29;
} else {
// Not a leap year
return 28;
}
}
function dateToDay(date) {
var feb = daysInFebruary(date.getFullYear());
var aggregateMonths = [0, // January
31, // February
31 + feb, // March
31 + feb + 31, // April
31 + feb + 31 + 30, // May
31 + feb + 31 + 30 + 31, // June
31 + feb + 31 + 30 + 31 + 30, // July
31 + feb + 31 + 30 + 31 + 30 + 31, // August
31 + feb + 31 + 30 + 31 + 30 + 31 + 31, // September
31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30, // October
31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, // November
31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, // December
];
return aggregateMonths[date.getMonth()] + date.getDate();
}
(是的,我实际上是在没有复制或粘贴的情况下做到了。如果有一种简单的方法我会生气)
答案 6 :(得分:3)
此方法考虑了时区问题和夏令时
function dayofyear(d) { // d is a Date object
var yn = d.getFullYear();
var mn = d.getMonth();
var dn = d.getDate();
var d1 = new Date(yn,0,1,12,0,0); // noon on Jan. 1
var d2 = new Date(yn,mn,dn,12,0,0); // noon on input date
var ddiff = Math.round((d2-d1)/864e5);
return ddiff+1;
}
(取自here)
另见fiddle
答案 7 :(得分:3)
如果您不想重新发明轮子,可以使用优秀的date-fns(node.js)库:
var getDayOfYear = require('date-fns/get_day_of_year')
var dayOfYear = getDayOfYear(new Date(2017, 1, 1)) // 1st february => 32
答案 8 :(得分:2)
Math.round((new date()。setHours(23) - new Date(new Date()。getFullYear(),0,1,0,0,0))/ 1000/86400);
进一步优化了答案。
此外,通过将setHours(23)或之后的两个零更改为另一个值,可以提供与另一个时区相关的日期。 例如,从欧洲检索位于美国的资源。
答案 9 :(得分:2)
我认为这更为直白:
var date365 = 0;
var currentDate = new Date();
var currentYear = currentDate.getFullYear();
var currentMonth = currentDate.getMonth();
var currentDay = currentDate.getDate();
var monthLength = [31,28,31,30,31,30,31,31,30,31,30,31];
var leapYear = new Date(currentYear, 1, 29);
if (leapYear.getDate() == 29) { // If it's a leap year, changes 28 to 29
monthLength[1] = 29;
}
for ( i=0; i < currentMonth; i++ ) {
date365 = date365 + monthLength[i];
}
date365 = date365 + currentDay; // Done!
答案 10 :(得分:1)
如果使用moment.js,我们可以获取甚至设置一年中的哪一天。
moment().dayOfYear();
//for getting
moment().dayOfYear(Number);
//for setting
moment.js 使用 this code 计算一年中的天
答案 11 :(得分:1)
Math.floor((Date.now() - Date.parse(new Date().getFullYear(), 0, 0)) / 86400000)
这是我的解决方法
答案 12 :(得分:0)
使用UTC时间戳的替代方案。另外,正如其他人所指出的那样,每月1日表示1而不是0.然而,月份从0开始。
var now = Date.now();
var year = new Date().getUTCFullYear();
var year_start = Date.UTC(year, 0, 1);
var day_length_in_ms = 1000*60*60*24;
var day_number = Math.floor((now - year_start)/day_length_in_ms)
console.log("Day of year " + day_number);
答案 13 :(得分:0)
我想提供一个解决方案来计算每个上个月的天数:
function getDayOfYear(date) {
var month = date.getMonth();
var year = date.getFullYear();
var days = date.getDate();
for (var i = 0; i < month; i++) {
days += new Date(year, i+1, 0).getDate();
}
return days;
}
var input = new Date(2017, 7, 5);
console.log(input);
console.log(getDayOfYear(input));
这样您就不必管理闰年和夏令时的细节。
答案 14 :(得分:0)
您可以在setDate
函数中传递参数作为日期编号:
var targetDate = new Date();
targetDate.setDate(1);
// Now we can see the expected date as: Mon Jan 01 2018 01:43:24
console.log(targetDate);
targetDate.setDate(365);
// You can see: Mon Dec 31 2018 01:44:47
console.log(targetDate)
答案 15 :(得分:0)
我已经制作了一个可读且非常快速的技巧,以及处理具有不同时区的JS Date对象。
我在时区,DST,闰秒和闰年中包含了不少测试用例。
P.S。与UTC不同,ECMA-262忽略了闰秒。如果您要将其转换为使用真实UTC的语言,则只需将{1}添加到oneDay
。
// returns 1 - 366
findDayOfYear = function (date) {
var oneDay = 1000 * 60 * 60 * 24; // A day in milliseconds
var og = { // Saving original data
ts: date.getTime(),
dom: date.getDate(), // We don't need to save hours/minutes because DST is never at 12am.
month: date.getMonth()
}
date.setDate(1); // Sets Date of the Month to the 1st.
date.setMonth(0); // Months are zero based in JS's Date object
var start_ts = date.getTime(); // New Year's Midnight JS Timestamp
var diff = og.ts - start_ts;
date.setDate(og.dom); // Revert back to original date object
date.setMonth(og.month); // This method does preserve timezone
return Math.round(diff / oneDay) + 1; // Deals with DST globally. Ceil fails in Australia. Floor Fails in US.
}
// Tests
var pre_start_dst = new Date(2016, 2, 12);
var on_start_dst = new Date(2016, 2, 13);
var post_start_dst = new Date(2016, 2, 14);
var pre_end_dst_date = new Date(2016, 10, 5);
var on_end_dst_date = new Date(2016, 10, 6);
var post_end_dst_date = new Date(2016, 10, 7);
var pre_leap_second = new Date(2015, 5, 29);
var on_leap_second = new Date(2015, 5, 30);
var post_leap_second = new Date(2015, 6, 1);
// 2012 was a leap year with a leap second in june 30th
var leap_second_december31_premidnight = new Date(2012, 11, 31, 23, 59, 59, 999);
var january1 = new Date(2016, 0, 1);
var january31 = new Date(2016, 0, 31);
var december31 = new Date(2015, 11, 31);
var leap_december31 = new Date(2016, 11, 31);
alert( ""
+ "\nPre Start DST: " + findDayOfYear(pre_start_dst) + " === 72"
+ "\nOn Start DST: " + findDayOfYear(on_start_dst) + " === 73"
+ "\nPost Start DST: " + findDayOfYear(post_start_dst) + " === 74"
+ "\nPre Leap Second: " + findDayOfYear(pre_leap_second) + " === 180"
+ "\nOn Leap Second: " + findDayOfYear(on_leap_second) + " === 181"
+ "\nPost Leap Second: " + findDayOfYear(post_leap_second) + " === 182"
+ "\nPre End DST: " + findDayOfYear(pre_end_dst_date) + " === 310"
+ "\nOn End DST: " + findDayOfYear(on_end_dst_date) + " === 311"
+ "\nPost End DST: " + findDayOfYear(post_end_dst_date) + " === 312"
+ "\nJanuary 1st: " + findDayOfYear(january1) + " === 1"
+ "\nJanuary 31st: " + findDayOfYear(january31) + " === 31"
+ "\nNormal December 31st: " + findDayOfYear(december31) + " === 365"
+ "\nLeap December 31st: " + findDayOfYear(leap_december31) + " === 366"
+ "\nLast Second of Double Leap: " + findDayOfYear(leap_second_december31_premidnight) + " === 366"
);
答案 16 :(得分:0)
这对于那些需要将一年中的日期作为字符串并具有jQuery UI的用户可能有用。
您可以使用jQuery UI Datepicker:
day_of_year_string = $.datepicker.formatDate("o", new Date())
在下面,它的作用与已经提到的某些答案((date_ms - first_date_of_year_ms) / ms_per_day
)相同:
function getDayOfTheYearFromDate(d) {
return Math.round((new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime()
- new Date(d.getFullYear(), 0, 0).getTime()) / 86400000);
}
day_of_year_int = getDayOfTheYearFromDate(new Date())
答案 17 :(得分:0)
也许可以帮助任何人
let day = (date => {
return Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24)
})(new Date())
答案 18 :(得分:0)
对于我们当中想要快速替代解决方案的人。
(function(){"use strict";
function daysIntoTheYear(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 ((
// 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);
}
// 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()+":\tday "+daysIntoTheYear(date)+"\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()+":\tday "+daysIntoTheYear(date)+"\t"+date);
// Performance Benchmark:
console.time("Speed of processing 65536 dates");
for (var i=0,month=date.getMonth()|0; i<65536; i=i+1|0)
date.setMonth(month=month+1+(daysIntoTheYear(date)|0)|0);
console.timeEnd("Speed of processing 65536 dates");
})();
一年中各个月份的大小以及Le年的工作方式非常适合使我们的时间与太阳同步。哎呀,它是如此完美,以至于我们所做的只是adjust mere seconds here and there。我们当前的of年系统自February 24th, 1582起一直有效,并且在可预见的将来很可能会保持有效。
DST可能会随时更改。可能是从现在开始的20年后,某个国家/地区可能会将DST的时间偏移一整天或其他极端时间。几乎肯定不会发生一整天的DST一天,但是DST仍然是实时的,犹豫不决的。因此,除了非常快之外,上述解决方案还可以用于将来的验证。
上面的代码片段运行非常快。我的计算机在Chrome上可以在大约52毫秒内处理65536个日期。
答案 19 :(得分:0)
const dayOfYear = date => {
const myDate = new Date(date);
const year = myDate.getFullYear();
const firstJan = new Date(year, 0, 1);
const differenceInMillieSeconds = myDate - firstJan;
return (differenceInMillieSeconds / (1000 * 60 * 60 * 24) + 1);
};
const result = dayOfYear("2019-2-01");
console.log(result);
答案 20 :(得分:0)
这是一个避免麻烦的Date对象和时区问题的解决方案,它要求您输入的日期格式为“ yyyy-dd-mm”。如果要更改格式,请修改date_str_to_parts函数:
function get_day_of_year(str_date){
var date_parts = date_str_to_parts(str_date);
var is_leap = (date_parts.year%4)==0;
var acct_for_leap = (is_leap && date_parts.month>2);
var day_of_year = 0;
var ary_months = [
0,
31, //jan
28, //feb(non leap)
31, //march
30, //april
31, //may
30, //june
31, //july
31, //aug
30, //sep
31, //oct
30, //nov
31 //dec
];
for(var i=1; i < date_parts.month; i++){
day_of_year += ary_months[i];
}
day_of_year += date_parts.date;
if( acct_for_leap ) day_of_year+=1;
return day_of_year;
}
function date_str_to_parts(str_date){
return {
"year":parseInt(str_date.substr(0,4),10),
"month":parseInt(str_date.substr(5,2),10),
"date":parseInt(str_date.substr(8,2),10)
}
}
答案 21 :(得分:0)
具有完整说明的直接解决方案。
var dayOfYear = function(date) {
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const [yyyy, mm, dd] = date.split('-').map(Number);
// Checks if February has 29 days
const isLeap = (year) => new Date(year, 1, 29).getDate() === 29;
// If it's a leap year, changes 28 to 29
if (isLeap(yyyy)) daysInMonth[1] = 29;
let daysBeforeMonth = 0;
// Slice the array and exclude the current Month
for (const i of daysInMonth.slice(0, mm - 1)) {
daysBeforeMonth += i;
}
return daysBeforeMonth + dd;
};
console.log(dayOfYear('2020-1-3'));
console.log(dayOfYear('2020-2-1'));
答案 22 :(得分:0)
我编写了这两个 javascript 函数,它们返回一年中的某一天(1 月 1 日 = 1)。 两者都是闰年。
function dayOfTheYear() {
// for today
var M=[31,28,31,30,31,30,31,31,30,31,30,31]; var x=new Date(); var m=x.getMonth();
var y=x.getFullYear(); if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) {++M[1];}
var Y=0; for (var i=0;i<m;++i) {Y+=M[i];}
return Y+x.getDate();
}
function dayOfTheYear2(m,d,y) {
// for any day : m is 1 to 12, d is 1 to 31, y is a 4-digit year
var m,d,y; var M=[31,28,31,30,31,30,31,31,30,31,30,31];
if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) {++M[1];}
var Y=0; for (var i=0;i<m-1;++i) {Y+=M[i];}
return Y+d;
}
答案 23 :(得分:-1)
/ *使用本脚本* /
null
答案 24 :(得分:-1)
将数学与日期函数混合时,我总是很担心(它很容易错过一些闰年的其他细节)。说你有:
var d = new Date();
我建议使用以下内容,日期将保存在day
:
for(var day = d.getDate(); d.getMonth(); day += d.getDate())
d.setDate(0);
看不出有什么理由不能正常工作(我不会那么担心几次迭代,因为这不会被如此密集地使用)。
答案 25 :(得分:-2)
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p id='out'></p>
<script>
let todaysDate = new Date();
let thisYear = todaysDate.getFullYear();
let thisMonth = todaysDate.getMonth();
let thisDay = todaysDate.getDate();
let months = new Array(12);
months[0] = 31;
months[1] = 59;
months[2] = 90;
months[3] = 120;
months[4] = 151;
months[5] = 181;
months[6] = 212;
months[7] = 243;
months[8] = 273;
months[9] = 304;
months[10] = 334;
months[11] = 365;
let month = months[thisMonth-1]
let dayYear = month+thisDay
document.getElementById('out').innerHTML = dayYear;
</script>
</body>
</html>