Javascript yılın gününü hesaplar (1-366)


119

1 - 366 arasında yılın gününü hesaplamak için javascript'i nasıl kullanırım? Örneğin:

  • 3 Ocak olmalıdır 3 .
  • 1 Şubat 32 olmalı .

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

Ama gerçekten ne demek istediğinden emin değilim. Sadece yıl içindeki gün sayısını mı istiyorsun? Veya iki tarih arasında?
Alex Turpin

16
fyi @ xeon06, artık yıl hesaplaması, 4'e göre mod'lamadan biraz daha karmaşıktır. bkz: artık yıl algoritması
Matt Felzani

4
@ Xeon06: Bu çoğu zaman doğru. Gönderen Vikipedi : onlar bu durumda, 400 ile bölünebilen eşit da sürece 100 ile bölünebilen eşit olan Yıl, artık yılları değil vardır artık yıllar.
Cameron

Ah, düzeltilmiş durumdayım. @minitech o zaman doğru cevaba sahip görünüyor.
Alex Turpin

Yanıtlar:


138

OP'nin düzenlemesinin ardından:

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

Düzenleme: Yukarıdaki kod başarısız olur ne zaman nowmart 26 ve 29 Ekim arasında bir tarihtir now'ın zamanında 1 am önce (örneğin 00:59:59). Bunun nedeni kodun yaz saati uygulamasını hesaba katmamasıdır. Bunu telafi etmelisiniz :

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.floorNisan ayında belirli bir günün ardından bana sürekli olarak beklenenden 1 gün daha kısa bir sonuç verdi. Math.ceilbeklendiği gibi çalıştı, ancak Math.roundbunun yerine kullanmanızın tavsiye edildiğini gördüm .
baacke

3
Gün bileşeni taban-1'dir. yani, bu yılın 1 Ocak'ını temsil etmek için new Date(2014, 0, 1), new Date(2014, 0, 0)buradaki gibi değil, kullanacaksınız . Bu kasıtlı mı? Belki de new Date(2014, 0, 0)geri döneceği gibi bir gün izinli olmanın açıklaması budur 12/31/2013.
Kirk Woll

1
Belki kullanmak .setUTCHoursve Date.UTC()daha güvenilir bir çözüm.
Noyo

6
@AlexTurpin, @ T30: Bunun biraz eski olduğunu biliyorum, ama merak ediyorsanız ... sorun Mart ayında başlayan Yaz Saati Uygulaması nedeniyle oluşuyor. Bunun nedeni, DST'den önceki bir tarihin gece yarısı ile DST'den sonraki bir tarihin gece yarısı arasındaki farkı aldığınızda, 1000 * 60 * 60 * 24'e eşit olarak bölünebilen bir milisaniye sayınızın olmayacağıdır (tam olarak bir saat kapalı olacaktır) . En kolay çözüm kullanmak ceilyerine kullanmaktır floor, bu size 1 Ocak = 1 olan bir numaralandırma sistemi verecektir. 1 Ocak = 0 istiyorsanız ( floorsize vereceği gibi), nihai sonucunuzdan 1 çıkarın.
Warren R.

2
var diff = now - start + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
Marlon

46

Bu, tüm ülkelerde Gün Işığından Yararlanma Saati değişikliklerinde geçerlidir (yukarıdaki "öğlen" Avustralya'da geçerli değildir):

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
Kabul edilen cevapta gün ışığından yararlanma ile ilgili hatalar olduğunu kabul edin. Yukarıdaki çözüm daha iyi ve daha hızlıdır. İşte jsPerf jsperf.com/date-getdayofyear-perf
Shyam Habarakada

@ShyamHabarakada: Kıyaslamanızdaki kod bozuk, getDay()olarak değiştirilmesi gerekiyor getDate(). İlki, günü değil haftanın gününü (0 = Pazar. 6 = Cumartesi) döndürür.
CodeManX

32

DST'ye tabi olmadığı için kimsenin UTC'yi kullanmayı düşünmemesini çok ilginç buluyorum. Bu nedenle, aşağıdakileri öneriyorum:

function daysIntoYear(date){
    return (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000;
}

Aşağıdakilerle test edebilirsiniz:

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

Artık yıl 2016 için hangi çıktılar ( http://www.epochconverter.com/days/2016 kullanılarak doğrulanmıştır ):

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

Bu, milisaniye sayısı çok büyük olduğu için taşabilir.
knt5784

@ knt5784 Matematik aşabilir, ancak onun örneği mümkün olan en büyük gerçek dünya değerinin iyi çalıştığını gösteriyor, bu nedenle tamsayı taşması olan tarayıcı tabanlı bir sorun yoksa bunu kullanmalısınız.
Per Fagrell

Ben şahsen bu yaklaşımı seviyorum. DST sorunlarını önlemenin çok daha temiz (ve çok akıllı!) Yolu. DOY'dan bugüne nasıl dönüş yapılacağını merak eden varsa, bu çok daha basittir. Temel olarak, sadece bir DOYth Ocak tarihi oluşturursunuz. Örneğin, 59 Ocak === 28 Şubat. Artık gün iyi işlenir. function doyToDate(doy, year) { return new Date(year, 0, doy); }
Kip

@ knt5784 En azından 200.000 yıl daha bu kodla milisaniye taşması riski yoktur. Date tarafından desteklenen en büyük tarih new Date(8640000000000000), hala daha küçüktür Number.MAX_SAFE_INTEGER. bu yanıta bakın: 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
Bu, tüy bırakmaz ... Size ait olmayan bir nesneyi, özellikle de küresel olanı değiştirmek. Bu, gün ışığından yararlanma süresinin 12 saatin üzerinde olduğu aşırı eğimli gezegenlerde de başarısız olur. Ancak daha gerçekçi bir şekilde, Date nesnesinin saat dilimini değiştirmeye izin veren bir tarayıcı için kod yazıyorsanız, j1'in saat dilimi Avustralya olabilir ve bunun saat dilimi, yuvarlamayı bozan Alaska olabilir.
Ray Foss

11

Neyse ki bu soru içinde bulunduğunuz günün sayısının gerekli olup olmadığını belirtmiyor ve bu cevaba yer bırakıyor.
Ayrıca bazı cevaplar (diğer sorular için de) artık yıl problemlerine sahipti veya Date nesnesini kullandı. Javascript'in Date object1 Ocak 1970'in her iki tarafında yaklaşık 285616 yılı (100.000.000 gün) kapsamasına rağmen , farklı tarayıcılarda (özellikle 0'dan 99'a kadar) her türlü beklenmedik tarih tutarsızlığından bıktım . Nasıl hesaplayacağımı da merak ediyordum.

Bir basit ve her şeyden yazdığı Yani, küçük algoritma hesaplamak için doğru ( ilerisini düşünerek Gregoryen : 2004 (madde 4.3.2.1), bu yüzden / Astronomik / ISO 8601 yıl0 var ve artık yıl olup negatif yıl desteklenmektedir Yılın gününü) dayalı yıl , ay ve gün .
O Not AD/BCgösterimde, yıl 0 AD / BC yok: yerine yıl 1 BCsıçrama yıllık olduğunu! BC notasyonunu hesaba katmanız gerekiyorsa, önce (aksi takdirde pozitif) yıl değerinden bir yıl çıkarın !!

Kısa devre bitmask-modulo leapYear algoritmasını değiştirdim (javascript için) ve ofsetlerin bit bazında aranması için sihirli bir sayı buldum (bu, jan ve feb hariç, bu nedenle 10 * 3 bit (30 bit, daha az 31 bit, böylece bitshift'e güvenli bir şekilde başka bir karakter kaydedebiliriz >>>)).

Ne ayın ne de günün olabileceğini unutmayın 0. Sadece bu denklemi gerekiyorsa o Bunun anlamı şu anki gün (kullanarak besleme .getMonth()) sadece kaldırmak gerekir --dan --m.

Bunun geçerli bir tarih varsaydığını unutmayın (hata denetimi sadece birkaç karakter daha fazladır).

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>


İşte doğru aralık doğrulamasına sahip sürüm .

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>

Yine, bir satır, ancak okunabilirlik için (ve aşağıdaki açıklamayı) 3 satıra böldüm.

Son satır yukarıdaki işlevle aynıdır, ancak (aynı) leapYear algoritması önceki bir kısa devre bölümüne (gün-sayı hesaplamasından önce) taşınır, çünkü aynı zamanda bir ayda ne kadar gün olduğunu bilmek gerekir. verilen (artık) yıl.

Ortadaki çizgi, başka bir sihirli sayı kullanarak belirli bir (artık) yılda belirli bir ay için doğru ofset numarasını (maksimum gün sayısı için) hesaplar : çünkü 31-28=3ve 3sadece 2 bit, sonra 12*2=24bit, 12 ayın tümünü saklayabiliriz. Toplama, çıkarma işleminden daha hızlı olabileceğinden, ofseti ekleriz (çıkarmak yerine 31). Şubat için artık yıl karar dalından kaçınmak için, bu sihirli arama numarasını anında değiştiriyoruz.

Bu bizi (oldukça açık) ilk satırla bırakır: ayın ve tarihin geçerli sınırlar içinde olduğunu kontrol eder ve falsearalık hatası durumunda bize bir dönüş değeri sağlar (bu işlevin de 0 döndüremeyeceğini unutmayın, çünkü 1 ocak 0000 kolay hata kontrollerinin yapılmasından, hala 1. gün) 'dir: if(r=dayNo(/*y, m, d*/)){}.
(Ay ve gün olmayabilir bu şekilde kullanılırsa 0), sonra bir değiştirebilirsiniz --m>=0 && m<12için m>0 && --m<12(başka kömürü tasarruf).
Onun 'için mevcut haliyle parçacığını yazdığınız nedeni 0 tabanlı ay değerleri için, biri sadece kaldırmak için ihtiyacı olduğu --gelen --m.

Ekstra:
Unutmayın, ayda sadece maksimum güne ihtiyacınız varsa bu günün aylık algoritmasını kullanmayın. Bu durumda daha verimli bir algoritma var (çünkü sadece ay Şubat olduğunda leepYear'a ihtiyacımız var) Bu soruyu cevap olarak gönderdim: JavaScript ile bir aydaki gün sayısını belirlemenin en iyi yolu nedir? .


1
Kullanım kolaylığı için bunu bir tarih işlevine ekledim. Date () tutarsızlıklarının hala bir sorun olduğunu kabul ediyorum, ancak 2015+ yıllarını kullanıyorum, bu yüzden tutarlı olduklarını umuyorum. Zavallı JSHint, kodunuzu doğrulamaya çalışırken öldü hahah. 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

Beğendiğine sevindim. Bu algo tamamen 0'a her iki tarafında (O (en> JavaScript tarih-nesnenin 7500 kez aralığı olduğunu, bir kuyruklu 2147483647) 2 ^ 31-1 yıldır test edilmiştir olabilir 2 ^ 32 için çalışmak, ama bu test etmedim hala). Ayrıca, yine benim cevap şöyle olabilir: Eğer kapalı tıraş edebilirsiniz +1dan this.getMonth()+1kaldırmak eğer --dan --m. DÜZENLE Yani, yapardım (bir kütüphane için):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

Aslında ona bakarken yaptım! Bir tane ekleyip hemen çıkardığımı fark ettim. Sanırım bundan 2^31 - 2016yıllar sonra js muhtemelen biraz modası geçmiş olacak.
freshvolk

@Freshvolk: lol, bu yüzden onu 2 ^ 31'den :)sonra hiç test etmedim Ama o zamana kadar en azından tahmin edilebilir ve tutarlı sonuçlar verecek haha. EDIT , sadece teorinin iyiliği için, leapyear için daha yavaş geleneksel all-modulo algo kullanarak, aralık 2 ^ 53'e kadar genişletilebilir. Ay arama algo sınırlayıcı faktör değildir.
GitaarLAB

5

Tekerleği yeniden icat etmek istemiyorsanız, mükemmel tarih-fns (node.js) kitaplığını kullanabilirsiniz:

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

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

4

Pekala, eğer seni doğru anlıyorsam, artık yılda 366, yoksa 365 istiyorsun, değil mi? Bir yıl, 4'e eşit olarak bölünebiliyorsa artık bir yıldır, ancak 400 ile bölünemezse 100 ile bölünemez:

function daysInYear(year) {
    if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
        // Leap year
        return 366;
    } else {
        // Not a leap year
        return 365;
    }
}

Güncellemeden sonra düzenle:

Bu durumda, yerleşik bir yöntem olduğunu düşünmüyorum; bunu yapmanız gerekecek:

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

(Evet, aslında bunu kopyalamadan veya yapıştırmadan yaptım. Kolay bir yolu varsa delireceğim)


Benim kolay yolum sadece 1054267675 numaralı sihirli numarayı kullanmak ve ona bir gün demek, hepsini yazmak için tembellik :)
yapıyorum

4

Bu, yıl içindeki içinde bulunulan günü bulmanın basit bir yoludur ve artık yılları sorunsuz bir şekilde hesaba katmalıdır:

JavaScript:

Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);

Google Apps Komut Dosyasında Javascript:

Math.round((new Date().setHours(23) - new Date(new Date().getYear(), 0, 1, 0, 0, 0))/1000/60/60/24);

Bu kodun birincil eylemi, cari yılda geçen milisaniye sayısını bulmak ve ardından bu sayıyı günlere dönüştürmektir. İçinde bulunduğumuz yılda geçen milisaniye sayısı, new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0)(Javascript) veya new Date(new Date().getYear(), 0, 1, 0, 0, 0)(Google Apps Komut Dosyası) ile elde edilen cari yılın ilk gününün ilk saniyesinin milisaniye sayısını milisaniyeden çıkararak bulunabilir. ile bulundu günün 23. saatinin new Date().setHours(23). Güncel tarihi 23. saate ayarlamanın amacı, yılın gününün doğru bir şekilde yuvarlanmasını sağlamaktır Math.round().

İçinde bulunduğunuz yılın milisaniye sayısını elde ettiğinizde, milisaniyeyi saniyeye dönüştürmek için 1000'e bölerek, ardından saniyeyi dakikaya dönüştürmek için 60'a bölerek, ardından dakikayı saate dönüştürmek için 60'a bölerek bu zamanı günlere dönüştürebilirsiniz. ve son olarak saati günlere dönüştürmek için 24'e bölerek.

Not: Bu gönderi, Google Apps Komut Dosyasında uygulanan JavaScript ve JavaScript arasındaki farkları hesaba katmak için düzenlendi. Ayrıca, cevap için daha fazla bağlam eklendi.


Lütfen işe yaradığını söylemekten biraz daha fazlasını açıklar mısınız?
Stephen Reindl

Evet! İlk başta daha fazla ayrıntı vermediğim için üzgünüm. "Math.round" ifadesinin içindeki ifade, yılın ilk gününü yılın o anki gününün son saatinin milisaniyesinden çıkararak mevcut yıldaki milisaniye sayısını bulur. Milisaniye sayısı daha sonra saniyeye dönüştürmek için 1000'e, dakikaya dönüştürmek için 60'a, saate dönüştürmek için 60'a ve günlere dönüştürmek için 24'e bölünür. İfade, yılın günü için bir tam sayıya yuvarlanacak şekilde bir "Math.round ()" işlevi içine sarılır.
Liz Page-Gould

Ayrıca, bu çözümün, her şeyi tek bir kod satırında yapması dışında "kabul edilen" çözümle aynı olduğunu da eklemeliyim.
Liz Page-Gould

Bu, gün ışığından yararlanma süresini nasıl açıklar? Bu biraz atmaz mı?
Dan Oswalt

Hayır, gün ışığından yararlanma saati bu hesaplamayı etkilemez çünkü gün ışığından yararlanma saati saat çözünürlüğüne sahiptir ve bu kod yıl içindeki gün sayısını hesaplar. Ayrıca .setHoursyöntemi ilk tarih nesnesinde kullandığım ve ikinci tarih nesnesi ile günün saatini belirttiğim için gün ışığından yararlanma saatinden 1 saatlik bir değişiklik bu hesaplamada kullanılan Date nesnelerinin saatlerini etkilemeyecektir.
Liz Page-Gould

4

Bunun daha basit olduğunu düşünüyorum:

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

Bu yöntem, saat dilimi sorununu ve yaz saati uygulamasını dikkate alır.

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

( buradan aldı )

Ayrıca bu kemana bakın


Bu biraz verimsiz ama mükemmel çalışıyor. Sadece nesneleri zaman alabilir ve setDate tarihi 1. güne değiştirebilir. Her ikisi de mükemmel şekilde desteklenir. Buradaki fikir, zaman dilimlerinde hareket etmeyeceğinizdir. Bu aynı zamanda gün ışığından yararlanma süresinin 12 saatten az olduğunu varsayar ... ki bu dünya için güvenli bir varsayımdır.
Ray Foss

2

Math.round ((new Date (). SetHours (23) - new Date (new Date (). GetFullYear (), 0, 1, 0, 0, 0)) / 1000/86400);

yanıtı daha da optimize eder.

Dahası, setHours (23) veya son fakat iki sıfırı sonradan başka bir değere değiştirerek, başka bir saat dilimiyle ilgili yılın gününü sağlayabilir. Örneğin, Amerika'da bulunan bir kaynağı Avrupa'dan almak için.


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

bu benim çözümüm


01 Ocak = DOY 01 yapmak için bir önceki yılın 31 Aralık tarihini kullandım. Ayrıca 10 Mart'ın 11 Mart ile aynı DOY değerine sahip olduğunu buldum çünkü biri 69 diğeri 69.9 bir şey, her ikisi de 69'a döşeme. Bunun yerine Math.round yapmak bunu düzeltti . 10 Mart ya da 11 Mart'ın, 11
Mart'ın

0

Okunabilir bir tane yaptım ve işi çok hızlı bir şekilde yapacak, aynı zamanda JS Date nesnelerini farklı saat dilimleriyle ele aldım.

Saat dilimleri, DST, artık saniyeler ve Artık yıllar için epeyce test senaryosu ekledim.

PS ECMA-262, UTC'den farklı olarak artık saniyeleri yok sayar. Bunu gerçek UTC kullanan bir dile dönüştürürseniz, sadece 1 'e ekleyebilirsiniz 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

Önceki her ayın günlerini ekleyerek hesaplamalar yapan bir çözüm sunmak istiyorum:

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

Bu şekilde artık yılların ve gün ışığından yararlanma tasarrufunun ayrıntılarını yönetmek zorunda kalmazsınız.


0

UTC zaman damgalarını kullanan bir alternatif. Ayrıca diğerlerinin de belirttiği gibi, ayda 1'i gösteren gün 0 yerine 1'dir. Bununla birlikte, ay 0'dan başlar.

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

Parametreyi setDatefonksiyonda tarih numarası olarak iletebilirsiniz :

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

Bu, dizge olarak yılın gününe ihtiyaç duyan ve jQuery kullanıcı arayüzüne sahip olanlar için yararlı olabilir.

JQuery UI Datepicker'ı kullanabilirsiniz:

day_of_year_string = $.datepicker.formatDate("o", new Date())

Altında, daha önce bahsedilen cevaplardan bazıları ile aynı şekilde çalışır ( (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

Aramızda hızlı alternatif çözüm arayanlar için.

(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");
})();

Yılın aylarının büyüklüğü ve Artık Yılların işleyiş şekli, zamanımızı güneşle birlikte yolda tutmak için mükemmel bir şekilde uyuyor. Heck, o kadar mükemmel çalışıyor ki yaptığımız tek şey sadece burada ve orada sadece saniyeleri ayarlamak . Mevcut artık yıl sistemimiz şu tarihten beri yürürlüktedir: 24 Şubat 1582'den yürürlüktedir ve öngörülebilir gelecekte büyük olasılıkla yürürlükte kalacaktır.

Ancak DST, değişikliğe çok açıktır. Bundan 20 yıl sonra, bazı ülkeler zamanı tam bir gün veya DST için başka bir aşırılıkla telafi edebilir. Tam bir DST günü neredeyse kesinlikle asla olmayacak, ancak DST yine de çok güncel ve kararsız. Bu nedenle, yukarıdaki çözüm, çok çok hızlı olmasının yanı sıra geleceğe yöneliktir.

Yukarıdaki kod parçacığı çok hızlı çalışıyor. Bilgisayarım, Chrome'da 65536 tarihi ~ 52 ms içinde işleyebiliyor.


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

Bu, sorunlu Date nesnesi ve saat dilimi sorunlarını ortadan kaldıran bir çözümdür, giriş tarihinizin "yyyy-gg-mm" biçiminde olmasını gerektirir. Biçimi değiştirmek istiyorsanız, date_str_to_parts işlevini değiştirin:

    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

Matematiği tarih işlevleriyle karıştırırken beni her zaman endişelendiriyor (bazı artık yılı diğer ayrıntıları kaçırmak çok kolay). Sahip olduğunuzu söyleyin:

var d = new Date();

Aşağıdakileri kullanmanızı öneririm, günler kaydedilecek day:

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

Bunun işe yaramaması için herhangi bir neden göremiyorum (ve bu kadar yoğun bir şekilde kullanılmayacağından birkaç yineleme için bu kadar endişelenmem).


-1

/ * BU YAZIYI KULLAN * /

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");
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.