Javascript计算一年中的哪一天(1-366)


118

如何使用javascript从1-366计算一年中的某一天?例如:

  • 1月3日应该是3 月3
  • 2月1日应该是32

4
var days = new Date().getFullYear() % 4 == 0 ? 366 : 365;
Alex Turpin

但实际上我不确定您的意思。您只想要一年中的天数?还是两个日期之间?
Alex Turpin

16
fyi @ xeon06,leap年的计算比4的修改复杂一些。请参阅:leap年算法
Matt Felzani

4
@ Xeon06:多数时候这是正确的。摘自Wikipedia:可以被100整除的年份不是leap年,除非它们也可以被400整除,在这种情况下,它们 leap年。
卡梅伦

嗯,我站住了。@minitech似乎有正确的答案。
Alex Turpin

Answers:


137

按照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点之前(如零时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);


5
Math.floor持续给我的结果比四月份的某一天少了1天。Math.ceil可以正常工作,但我建议您Math.round不要使用任何一种。
baacke 2014年

3
日部分是以1为底的。也就是说,代表今年1月1日,您将使用new Date(2014, 0, 1),而不是new Date(2014, 0, 0)此处的样子。那是故意的吗?也许这就是new Date(2014, 0, 0)要归还一天的原因12/31/2013
Kirk Woll

1
也许使用.setUTCHoursDate.UTC()以获得更可靠的解决方案。
2014年

6
@ AlexTurpin,@ T30:我知道这有点旧,但是如果您想知道...问题是由于三月份开始的夏令时引起的。这是因为当您采用DST之前的某个日期的午夜与DST之后的某个日期的午夜之间的差值时,您将不会有毫秒数可以被1000 * 60 * 60 * 24整除(这将是整整一个小时的时间) 。最简单的解决方案是使用ceil而不是floor,这将为您提供一个编号系统,其中Jan 1st =1。如果您希望Jan 1st = 0(如您所愿floor),则从最终结果中减去1。
沃伦·

2
要考虑时区和夏令时,请将第3行更改为: var diff = now - start + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
Marlon 2015年

46

这适用于所有国家/地区的夏令时更改(上述“中午”不适用于澳大利亚):

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;
};

1
同意接受的答案中存在与夏令时相关的错误。上述解决方案更好,更快。这是我在jsPerf上测试的一种变体jsperf.com/date-getdayofyear-perf
Shyam Habarakada 2014年

@ShyamHabarakada:基准测试中的代码已损坏,getDay()需要更改为getDate()。前者返回星期几(0 =星期日..6 =星期六),而不是星期几。
CodeManX

32

我发现非常有趣的是,没有人考虑使用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年leap年的输出(使用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

由于毫秒数太大,可能会溢出。
knt5784

@ knt5784数学可能会溢出,但他的示例显示了可能的最大实际值,可以正常工作,因此,除非存在基于浏览器的整数溢出问题,否则您应该可以使用它。
Per Fagrell

我个人喜欢这种方法。避免DST问题的更简洁(而且非常聪明!)的方法。如果有人想知道如何从DOY转换为最新版本,则要简单得多。基本上,您只需创建一个日期DOYth。例如,1月59日=== 2月28日。Le日将被罚款。function doyToDate(doy, year) { return new Date(year, 0, doy); }
基普

@ knt5784此代码没有毫秒级溢出的风险,至少在接下来的200,000年内没有。Date支持的最大日期为new Date(8640000000000000),但仍小于Number.MAX_SAFE_INTEGER。看到这个答案:stackoverflow.com/a/11526569/18511
Kip

18
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
这不会传递皮棉...修改不是您的对象,尤其是全局对象。在夏令时超过12小时的极端倾斜的行星上,这也会失败。但更现实的是,如果您为允许更改Date对象的时区的浏览器进行编码,则j1的时区可能是澳大利亚,而该时区则可能是阿拉斯加,这将舍入。
雷·福斯

11

幸运的是,如果数量这个问题没有指定当前需要一天,留有余地这个答案。
还有一些答案(也针对其他问题)有had年问题或使用了Date对象。尽管javascript Date object在1970年1月1日的任一侧涵盖了大约285616年(100,000,000天),但我对不同浏览器中各种意外的日期不一致感到厌烦(最著名的是0到99年)。我也很好奇如何计算。

所以我写了一个简单的,最重要的是小的算法来计算正确的年份Proleptic Gregorian / Astronomical / ISO 8601:2004(条款4.3.2.1),因此年份0存在并且是a年,并且支持负年份)根据
请注意,在AD/BC符号中,不存在AD / BC 0年:相反,year 1 BC是the年!如果您需要考虑BC表示法,则只需先减去一年(否则为正数)年值即可!!

我修改了(对于javascript) 短路bitmask-modulo jumpYear算法,并想出了一个魔术数字来逐位查找偏移量(不包括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行。

最后一行与上面的函数相同,但是(完全相同的)pumpYear算法移到了之前的短路部分(在计算天数之前),因为还需要知道一个月中有多少天给定的(le年)。

中间一行使用另一个幻数来计算给定(le)年中给定月份的正确偏移量数字(最大天数):由于31-28=33仅2位,则12*2=24位可以存储所有12个月。由于加法可以快于减法,因此我们增加了偏移量(而不是从中减去31)。为避免2月发生a年决策分支,我们会即时修改该魔术查找编号。

这让我们留下了(非常明显的)第一行:它检查月份和日期是否在有效范围之内,并确保false在范围错误时返回值(请注意,此函数也不应返回0,因为1 jan 0000仍然是第一天。),提供了简单的错误检查功能:if(r=dayNo(/*y, m, d*/)){}
如果以这种方式使用(月份和日期可能不是0),则可以更改--m>=0 && m<12m>0 && --m<12(保存另一个字符)。
我以当前格式键入代码段的原因是,对于从0开始的月份值,只需删除----m

额外:
请注意,如果您只需要每月最大天数,请不要使用这一天的每月算法。在那种情况下,有一个更有效的算法(因为当月是二月时我们只需要leepYear)我回答了这个问题:用javascript确定一个月的天数的最佳方法是什么?


1
我将其放入日期函数中以便于使用。虽然授予Date()不一致仍然是一个问题,但是我使用的是2015年以上的年份,所以我希望它们是一致的。可怜的JSHint在尝试验证您的代码时死了哈哈。Date.prototype.dayNo = function(){ var y = this.getFullYear(); var m = this.getMonth()+1; var d = this.getDate(); return --m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+d; };
freshvolk 2015年

很开心你喜欢。该算法在0的两侧都经过2 ^ 31-1年的全面测试(高达2147483647,这是javascript的date-object范围的> 7500倍)(可能适用于2 ^ 32,但我没有测试过)然而)。此外,您可能会再次读我的回答:你可以刮掉+1this.getMonth()+1如果删除了----m编辑所以,我会做(对于图书馆):Date.prototype.dayNo = function(){ var y=this.getFullYear(), m=this.getMonth(); return m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+this.getDate(); };
GitaarLAB

当我看着它时,我实际上就是这样做的!我意识到我要先加一个,然后立即减去。我认为到2^31 - 2016现在为止的几年时间,js可能已经有点过时了。
freshvolk 2015年

@Freshvolk:大声笑,这就是为什么我从未在2 ^ 31 :)之后测试它,但是在那之前,它至少会给出可预测和一致的结果。编辑,仅出于理论上的考虑,使用较慢的常规全模算法进行leap年,范围可以扩展到2 ^ 53。月度查找算法不是限制因素。
GitaarLAB

5

如果您不想重新发明轮子,可以使用出色的date-fns(node.js)库:

var getDayOfYear = require('date-fns/get_day_of_year')

var dayOfYear = getDayOfYear(new Date(2017, 1, 1)) // 1st february => 32

4

好吧,如果我对您的理解正确,那么您想要a年366,否则要365,对吧?如果一年可以被4整除而不是被100整除,那么它就是a年,除非也可以被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();
}

(是的,我实际上是这样做的,没有复制或粘贴。如果有一种简单的方法,我会生气的)


我最简单的方法就是使用魔法数字1054267675并将其命名为“ day”,我很懒惰键入所有内容:)
GitaarLAB 2015年

4

这是查找一年中当前日期的简单方法,并且应该可以毫无问题地说明leap年:

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)或new Date(new Date().getYear(), 0, 1, 0, 0, 0)(Google Apps Script)获得的当年第一天的第一秒的毫秒数来找到当年已过去的毫秒数。是在当天23号小时中找到的new Date().setHours(23)。将当前日期设置为23小时的目的是确保正确地将一年中的日期四舍五入Math.round()

掌握了当年的毫秒数后,您可以将此时间转换为天数,方法是:除以1000,将毫秒转换为秒,然后除以60,将秒转换为分钟,然后除以60,将分钟转换为小时,最后除以24可将小时数转换为天数。

注意:本文经过修改,以解决JavaScript与Google Apps脚本中实现的JavaScript之间的差异。此外,为答案添加了更多上下文。


您能否解释一下,而不只是说它在起作用?
Stephen Reindl

是! 抱歉,我没有提供更多详细信息。“ Math.round”语句中的表达式通过从当年当天的最后一小时的毫秒数中减去一年中的第一天来找到当年的毫秒数。然后,将毫秒数除以1000转换为秒,将60转换为分钟,将60转换为小时,将24转换为天。该表达式包含在“ Math.round()”函数中,因此可以在一年中四舍五入为整数。
Liz Page-Gould

我还应该补充一点,该解决方案与“接受的”解决方案基本相同,只是它可以在一行代码中完成所有工作。
Liz Page-Gould

如何计算夏令时?那不会丢掉它吗?
丹·奥斯瓦尔特

不,夏令时不会影响此计算,因为夏令时具有小时的分辨率,并且此代码正在计算一年中的天数。此外,由于我.setHours在第一个日期对象上使用了该方法,并为第二个日期对象指定了一天中的时间,因此,从夏时制更改1小时不会影响此计算中使用的Date对象的时间。
Liz Page-Gould

4

我认为这更简单:

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!

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; 
}

(从这里

另请参阅此小提琴


这有点低效,但是效果很好。您可以获取对象的时间,然后setDate将日期更改为第1天。这两种方法都得到了完美的支持。这个想法是您不会在时区移动。这还假设夏令时少于12小时...这在地球上是一个安全的假设。
雷·福斯

2

Math.round((new Date()。setHours(23)-new Date(new Date()。getFullYear(),0,1,0,0,0))/ 1000/86400);

进一步优化答案。

此外,通过将setHours(23)或稍后的最后一个但两个零更改为另一个值,可以提供与另一个时区相关的年度日期。例如,要从欧洲检索位于美国的资源。


1
Math.floor((Date.now() - Date.parse(new Date().getFullYear(), 0, 0)) / 86400000)

这是我的解决方案


我使用上一年的12月31日来确定1月1日= DOY01。我还发现3月10日与3月11日具有相同的DOY,因为一个是69,另一个是69.9,都降到了69。 。我相信,无论是3月10日或3月11日是夏令时间开关,它会导致3月11日至不太会DOY 70
user3015682

0

我已经编写了一个可读性强的代码,并且可以很快完成该任务,并且可以处理具有不同时区的JS Date对象。

我已经包含了许多时区,DST,leap秒和Le年的测试用例。

与UTC不同,PS ECMA-262忽略leap秒。如果要将其转换为使用实际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"
);


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));

这样,您就不必管理of年和夏令时的详细信息。


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);

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)

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())

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年的工作方式非常适合使我们的时间与太阳同步。哎呀,它是如此完美地工作,以至于我们所要做的只是到处调整几秒钟。我们目前的current年制度自 1582 2月24日,并且在可预见的将来可能会继续有效。

但是,DST可能会随时更改。可能是从现在开始的20年后,某个国家/地区可能会将DST的时间偏移一整天或其他极端时间。几乎肯定不会发生一整天的DST一天,但是DST仍然是实时的,犹豫不决的。因此,除了非常非常快之外,上述解决方案还可以用于未来。

上面的代码片段运行非常快。我的计算机在Chrome上可以在大约52毫秒内处理65536个日期。


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);


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)
    }
}

-1

当我将数学与日期函数混合在一起时,我总是很担心(很容易错过leap年的其他细节)。说您有:

var d = new Date();

我建议使用以下内容,以节省几天的时间day

for(var day = d.getDate(); d.getMonth(); day += d.getDate())
    d.setDate(0);

看不出为什么它不能正常工作的任何原因(我不会担心很少的迭代,因为不会如此频繁地使用它)。


-1

/ *使用此脚本* /

var today = new Date();
var first = new Date(today.getFullYear(), 0, 1);
var theDay = Math.round(((today - first) / 1000 / 60 / 60 / 24) + .5, 0);
alert("Today is the " + theDay + (theDay == 1 ? "st" : (theDay == 2 ? "nd" : (theDay == 3 ? "rd" : "th"))) + " day of the year");
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.