JavaScriptを使用して、1日から366日までの年の日を計算するにはどうすればよいですか?例えば:
- 1月3日は、する必要があります3。
- 2月1日は32にする必要があります。
JavaScriptを使用して、1日から366日までの年の日を計算するにはどうすればよいですか?例えば:
回答:
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);
編集:上記のコードは、3月26日から10月29日までの日付で、時刻が午前1時(たとえば00:59:59)の場合は失敗します。これは、コードが夏時間を考慮していないためです。これを補う必要があります:nownow
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);
Math.floor4月の特定の日の後、予想よりも1日少ない結果が一貫して得られました。Math.ceil期待どおりに動作しましたがMath.round、どちらかではなく使用することをお勧めします。
new Date(2014, 0, 1)しませんnew Date(2014, 0, 0)。それは意図的ですか?おそらく、それnew Date(2014, 0, 0)が戻ってくるように1日ずれていることの説明です12/31/2013。
.setUTCHoursしDate.UTC()ます。
ceilなくを使用floorすることです。これにより、Jan 1st = 1の番号付けシステムが得られます。Jan1st = 0が必要な場合は(floor最終的に)、1を減算すると、最終結果が得られます。
var diff = now - start + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
これは、すべての国の夏時間の変更全体で機能します(上記の「正午」はオーストラリアでは機能しません)。
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;
};
getDay()ため、に変更する必要がありますgetDate()。前者は、曜日ではなく曜日(0 = Sunday..6 = Saturday)を返します。
UTCはDSTの対象ではないため、誰もUTCの使用を検討していなかったことは非常に興味深いと思います。したがって、以下を提案します。
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
function doyToDate(doy, year) { return new Date(year, 0, doy); }
new Date(8640000000000000)、それでもまだですNumber.MAX_SAFE_INTEGER。この回答を参照してください:stackoverflow.com/a/11526569/18511
Date.prototype.dayOfYear= function(){
var j1= new Date(this);
j1.setMonth(0, 0);
return Math.round((this-j1)/8.64e7);
}
alert(new Date().dayOfYear())
多くの場合は幸運なことに、この質問には、指定されていない現在の日が必要とされるこの回答の余地を残して、。
また、いくつかの回答(他の質問についても)にはうるう年の問題があるか、Dateオブジェクトが使用されていました。Date object1970年1月1日のどちらの側でも、javascript は約285616年(1億日)をカバーしますが、さまざまなブラウザー(特に0から99年)間でのあらゆる種類の予期しない日付の不一致にうんざりしました。計算方法にも興味がありました。
だから私は正しい(Proleptic Gregorian / Astronomical / ISO 8601:2004(clause 4.3.2.1))を計算するためのシンプルで何よりも小さなアルゴリズムを書いたので、年が存在し、うるう年であり、負の年がサポートされています)年、月、日に基づいて。表記では、0年のAD / BCは存在しない
ことに注意してください。代わりに、年はうるう年です。BC表記を考慮する必要がある場合は、最初に(そうでなければ正の)年の値から1年を引くだけです!! 0AD/BC1 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>
繰り返しますが、1行ですが、読みやすくするために3行に分割しています(および以下の説明)。
最後の行は上記の関数と同じですが、(同一の)leapYearアルゴリズムは、前の短絡セクション(日数計算の前)に移動されます。これは、1か月の日数を知る必要があるためです。与えられた(うるう)年。
中央の線は正しい計算オフセット別のマジックナンバーを使用して、指定された(うるう年)年で与えられた月の(日数の最大数の)数を:以来31-28=3と3その後、わずか2ビットである12*2=24ビット、我々はすべての12ヶ月保存することができます。足し算は引き算よりも速いため、オフセットを(から引き算するのではなく)追加し31ます。2月のうるう年の決定分岐を避けるために、その魔法の検索番号をその場で変更します。
(かなり明白な)最初の行が残ります:月と日付が有効な範囲内にあることを確認し、false範囲エラーの戻り値を保証します(この関数も0を返すことができないはずです。1jan 0000まだ1日目です。簡単なエラーチェックを提供しますif(r=dayNo(/*y, m, d*/)){}。
(月と日がないかもしれないこの方法を使用した場合0)、そして1は変更することができます--m>=0 && m<12にm>0 && --m<12(別の文字を保存します)。
私はそれの現在の形でのスニペットを入力した理由は、0ベースの月の値のために、1だけで削除する必要があることです--から--m。
補足:月あたりの最大日数だけが必要な場合は、この日の月間アルゴリズムを使用しないでください。その場合、より効率的なアルゴリズムがあります(月が2月の場合はleepYearだけが必要なため)私はこの質問に答えて投稿しました:JavaScriptで月の日数を決定する最良の方法は何ですか?。
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; };
+1からthis.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(); };
2^31 - 2016今から何年もたつまでに、jsはおそらく少し時代遅れになると思います。
:)、それまでは、少なくとも予測可能な一貫した結果が得られます。EDITは、理論上、うるう年の従来の遅いすべてのモジュロアルゴを使用して、範囲を2 ^ 53に拡張できます。月ルックアップアルゴは制限要因ではありません。
ええと、私があなたを正しく理解していれば、うるう年には366、それ以外の場合は365が必要ですか?1年は、4で割り切れる場合はうるう年ですが、400で割り切れる場合を除き、100は割り切れません。
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();
}
(はい、実際にはコピーも貼り付けもせずにそれを行いました。簡単な方法があれば私は怒るでしょう)
:)
これは、年の現在の日付を見つける簡単な方法であり、うるう年を問題なく考慮する必要があります。
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 Scriptに実装されたJavaScriptの違いを考慮して編集されています。また、回答のコンテキストが追加されました。
.setHours最初の日付オブジェクトでこのメソッドを使用し、2番目の日付オブジェクトで時刻を指定したため、夏時間から1時間変更しても、この計算で使用される日付オブジェクトの時刻には影響しません。
これはもっと簡単だと思います:
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!
この方法では、タイムゾーンの問題と夏時間を考慮します
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;
}
(ここから)
このフィドルも参照してください
Math.floor((Date.now() - Date.parse(new Date().getFullYear(), 0, 0)) / 86400000)
これは私の解決策です
私は、読みやすく、非常にすばやくトリックを実行できるように作成しました。また、タイムゾーンが異なるJS Dateオブジェクトを処理します。
タイムゾーン、DST、うるう秒、うるう年のテストケースをかなり含めました。
PS ECMA-262は、UTCとは異なり、うるう秒を無視します。これを実際の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"
);
前月の日数を追加して計算するソリューションを提供したいと思います。
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));
これにより、うるう年や夏時間の詳細を管理する必要がなくなります。
UTCタイムスタンプを使用する別の方法。また、他の人が指摘したように、月の最初を示す日は0ではなく1です。ただし、月は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);
これは、年の日を文字列として必要とし、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())
高速な代替ソリューションが必要な私たちの間で。
(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");
})();
年間の月のサイズとうるう年の働き方は、太陽に順応するために私たちの時間を完全に適合させます。一体、それは完璧に機能するので、私たちがやっていることは、ほんの数秒をあちこち調整するだけです。現在のうるう年のシステムは、1582年2月24日から有効です。有効であり、近い将来も有効であると思われます。
ただし、DSTは非常に変更される可能性があります。20年後のことかもしれませんが、国によっては、丸1日またはDSTのその他の極端な時間で時間を相殺する場合があります。DSTが丸一日続くことはほぼ確実にありませんが、それでもDSTは非常に活発で決断力がありません。したがって、上記のソリューションは、非常に高速であることに加えて、将来の証明となります。
上記のコードスニペットは非常に高速に実行されます。私のコンピュータはChromeで65536の日付を約52ミリ秒で処理できます。
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);
これは、厄介な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)
}
}
数学と日付関数を混在させると、常に心配になります(うるう年の他の詳細を見逃すのは簡単です)。あなたが持っているとしましょう:
var d = new Date();
私は以下を使用することをお勧めします、日は保存されdayます:
for(var day = d.getDate(); d.getMonth(); day += d.getDate())
d.setDate(0);
これがうまく機能しない理由を見つけることができません(これはあまり集中的に使用されないため、いくつかの反復についてはそれほど心配しません)。
/ *このスクリプトを使用* /
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");
var days = new Date().getFullYear() % 4 == 0 ? 366 : 365;