İnsan dostu göreli tarih biçimlendirmesi için Javascript kitaplığı [kapalı]


95

Bazı tarihleri ​​güncel tarihe göre insan dostu bir formatta görüntülemek istiyorum.

İnsan dostu akraba tarihlere örnekler:

  • 10 saniye önce
  • 20 dakika sonra
  • 1 gün önce
  • 5 hafta önce
  • 2 ay önce

Temelde aslına sadık kalarak en yüksek büyüklük sırasını korumak (ve tercihan, yalnızca bu birimlerden 2'sini geçerken birimleri yukarı kaydırmak - 1 ay yerine 5 hafta).

Yine de daha az kontrole sahip ve daha dostane tarihlere sahip bir kütüphaneyle yaşayabilirdim:

  • dün
  • yarın
  • geçen hafta
  • birkaç dakika önce
  • birkaç saat içinde

Bunun için herhangi bir popüler kütüphane var mı?


Neden "1 gün önce", yalnızca gerçek tarih ve saati sunmaktan daha "insan dostu"?
RobG

5
@RobG Daha çok bağlam değiştirmekten kaçınmakla ilgili olduğunu söyleyebilirim, örneğin çoğunlukla metin olan ve okunan bir sayfada, bağlam anahtarı örneğin aa / gg / yy'ye geçiş duraklamaya neden olabilir. Bir veri tablosunda bu biçimi kullanmak daha okunaklı olabilir. Aynı zamanda okuyucunun tarihle ne yapması gerektiğine de bağlıdır, örneğin "bu n gün önce oldu" mu yoksa "1/1/1972 tarihinden önce mi oldu" eyleme geçirilebilir mi yoksa okuyucunun bağlamına uygun mu?
wprl

Belki, ama olayların bir listesini "Dün ... 3 gün önce ... 10 / Mayıs ..." olarak görmek kafa karıştırıcı. Yine de ne zaman meydana geldiklerinin bir resmini çekmek için hepsini kafamda tarihlere dönüştürmem gerekiyor. Tarihler kısa ve kesindir, "zaman öncesi" değerleri konuşmaya yöneliktir, kesinlikten yoksundur ve genellikle yalnızca ilişkili tarih için faydalıdır. Belki sadece benim, ama belki değil. :-)
RobG

6
İçeriğe bağlı olduğunu söyleyebilirim. Sonuçta, aslında dün olsaydı, "17 Şubat 2014'te balığa gittim" demezdiniz. Orada çok daha fazla beyin duraklama var. Bu tür bir metin, son olayların bir listesi için mükemmeldir.
Simon Williams

2
@RobG Sadece bizim gibi inekler normal insanlar değil böyle düşünüyor.

Yanıtlar:


94

Bu cevabı yazdığımdan beri, iyi bilinen bir kitaplık moment.js'dir .


Kullanılabilir kütüphaneler var , ancak bunu kendiniz uygulamak önemsizdir. Sadece birkaç koşul kullanın.

Bir karşılaştırma yapmak istediğiniz zaman için datesomutlaştırılmış bir Datenesne olduğunu varsayın .

// Make a fuzzy time
var delta = Math.round((+new Date - date) / 1000);

var minute = 60,
    hour = minute * 60,
    day = hour * 24,
    week = day * 7;

var fuzzy;

if (delta < 30) {
    fuzzy = 'just then.';
} else if (delta < minute) {
    fuzzy = delta + ' seconds ago.';
} else if (delta < 2 * minute) {
    fuzzy = 'a minute ago.'
} else if (delta < hour) {
    fuzzy = Math.floor(delta / minute) + ' minutes ago.';
} else if (Math.floor(delta / hour) == 1) {
    fuzzy = '1 hour ago.'
} else if (delta < day) {
    fuzzy = Math.floor(delta / hour) + ' hours ago.';
} else if (delta < day * 2) {
    fuzzy = 'yesterday';
}

Gelecekteki tarihlerin üstesinden gelmek için bunu uyarlamanız gerekir.


9
Dün, son gece yarısından önce, 24 saat ile 48 saat arasında değil.
mxcl

@mmaclaurin Mine asla tam bir çözüm olarak tasarlanmadı, sadece doğru yönde bir işaretçi. Daha sonra güncellemek için bir not yazacağım veya isterseniz yanıtı düzenlemekten çekinmeyin.
alex

Lütfen tarih-fns'ye de bir göz atın ! Kod tabanınızı küçük tutmak istiyorsanız bu harika bir kitaplık, çünkü momentj'lerden çok daha az yer kaplar!
mesqueeb

1
Twitter tarzı bir getTimeAgoişlev yapmak için bu kodu değiştirdim gist.github.com/pomber/6195066a9258d1fb93bb59c206345b38
pomber

87

Bunu yapan bir tarih kitaplığı olan moment.js'yi yazdım . Yaklaşık 5 KB (2011) 52 KB (2019) ve tarayıcılarda ve Node'da çalışıyor. Aynı zamanda muhtemelen JavaScript için en popüler ve ünlü tarih kitaplığıdır.

Timeago, biçimlendirme, ayrıştırma, sorgulama, işleme, i18n vb. Destekler.

Geçmişteki tarihler için Timeago (göreceli zaman) ile yapılır moment().fromNow(). Örneğin, 1 Ocak 2019'u timeago biçiminde görüntülemek için:

let date = moment("2019-01-01", "YYYY-MM-DD");
console.log(date.fromNow());
<script src="https://momentjs.com/downloads/moment.min.js"></script>

Timeago dizeleri ile özelleştirilebilir moment.updateLocale(), böylece onları uygun gördüğünüz şekilde değiştirebilirsiniz.

Kesintiler, sorunun istediği şeyler değildir ("5 hafta" - "1 ay"), ancak hangi zaman aralığı için hangi dizelerin kullanıldığı belgelenmiştir.


1
Tarayıcıda ve düğümde çalışmasını sağladığınız için teşekkürler !!!!
wprl

50
ha bu boyut güncellemesi olsa!
Askdesigners

1
Lütfen tarih-fns'ye de bir göz atın ! Kod tabanınızı küçük tutmak istiyorsanız bu harika bir kitaplık, çünkü momentj'lerden çok daha az yer kaplar!
mesqueeb

Bu kütüphane kadar iyi, cevap, bir sayının onu kullanarak insan dostu bir şekilde nasıl biçimlendirileceğine dair bir açıklama içermiyor
Code Whisperer

Siz de "kullanımdan kaldırma" ile güncelleme yapacak mısınız? momentjs.com/docs/#/-project-status
Juan De la Cruz

17

İşte John Resig'den bir şey - http://ejohn.org/blog/javascript-pretty-date/

DÜZENLEME (6/27/2014): Sumurai8'den gelen yorumu takiben - bağlantılı sayfa hala çalışıyor olsa da, işte pretty.jsyukarıdaki makaleden bağlantı için alıntı :

pretty.js

/*
 * JavaScript Pretty Date
 * Copyright (c) 2011 John Resig (ejohn.org)
 * Licensed under the MIT and GPL licenses.
 */

// Takes an ISO time and returns a string representing how
// long ago the date represents.
function prettyDate(time) {
    var date = new Date((time || "").replace(/-/g, "/").replace(/[TZ]/g, " ")),
        diff = (((new Date()).getTime() - date.getTime()) / 1000),
        day_diff = Math.floor(diff / 86400);

    if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31) return;

    return day_diff == 0 && (
    diff < 60 && "just now" || diff < 120 && "1 minute ago" || diff < 3600 && Math.floor(diff / 60) + " minutes ago" || diff < 7200 && "1 hour ago" || diff < 86400 && Math.floor(diff / 3600) + " hours ago") || day_diff == 1 && "Yesterday" || day_diff < 7 && day_diff + " days ago" || day_diff < 31 && Math.ceil(day_diff / 7) + " weeks ago";
}

// If jQuery is included in the page, adds a jQuery plugin to handle it as well
if (typeof jQuery != "undefined") jQuery.fn.prettyDate = function() {
    return this.each(function() {
        var date = prettyDate(this.title);
        if (date) jQuery(this).text(date);
    });
};

Kullanım:

prettyDate("2008-01-28T20:24:17Z") // => "2 hours ago"
prettyDate("2008-01-27T22:24:17Z") // => "Yesterday"
prettyDate("2008-01-26T22:24:17Z") // => "2 days ago"
prettyDate("2008-01-14T22:24:17Z") // => "2 weeks ago"
prettyDate("2007-12-15T22:24:17Z") // => undefined

Kullanımla ilgili makaleden alıntı:

Örnek Kullanım

Aşağıdaki örneklerde, sitedeki başlığında tarih bulunan tüm çapaların iç metni olarak güzel bir tarihe sahip olmasını sağlıyorum. Ek olarak, sayfa yüklendikten sonra her 5 saniyede bir bağlantıları güncellemeye devam ediyorum.

JavaScript ile:

function prettyLinks(){
    var links = document.getElementsByTagName("a");
    for ( var i = 0; i < links.length; i++ )
        if ( links[i].title ) {
            var date = prettyDate(links[i].title);
            if ( date )
                links[i].innerHTML = date;
        }
}
prettyLinks();
setInterval(prettyLinks, 5000);

JQuery ile:

$("a").prettyDate();
setInterval(function(){ $("a").prettyDate(); }, 5000);

Faiz: Orijinal kodda bazı değişiklikler, hata düzeltmeleri ve iyileştirmeler yapıldı.

function prettyDate(time) {
    var date = new Date((time || "").replace(/-/g, "/").replace(/[TZ]/g, " ")),
        diff = (((new Date()).getTime() - date.getTime()) / 1000),
        day_diff = Math.floor(diff / 86400);
    var year = date.getFullYear(),
        month = date.getMonth()+1,
        day = date.getDate();

    if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31)
        return (
            year.toString()+'-'
            +((month<10) ? '0'+month.toString() : month.toString())+'-'
            +((day<10) ? '0'+day.toString() : day.toString())
        );

    var r =
    ( 
        (
            day_diff == 0 && 
            (
                (diff < 60 && "just now")
                || (diff < 120 && "1 minute ago")
                || (diff < 3600 && Math.floor(diff / 60) + " minutes ago")
                || (diff < 7200 && "1 hour ago")
                || (diff < 86400 && Math.floor(diff / 3600) + " hours ago")
            )
        )
        || (day_diff == 1 && "Yesterday")
        || (day_diff < 7 && day_diff + " days ago")
        || (day_diff < 31 && Math.ceil(day_diff / 7) + " weeks ago")
    );
    return r;
}

1
Merhaba Floyd, cevabınıza bazı değişiklikler (hata düzeltme, iyileştirmeler) ekledim. Umarım aldırmazsın ..
Faiz

İyi bir! Ancak zaman damgası sayısal türü ile çalışmayın, belki if (typeof time == 'string') {time = time.replace (/ - / g, "/").replace(/[TZ]/ gibi daha iyi bir filtreye ihtiyacınız olabilir. g, "")); }
Arthur Araújo

Lütfen gelecekteki tarihler nasıl hesaplanır? Şu andan itibaren 2 gün gibi.
Ikenna Emman

15

sugar.js harika tarih biçimlendirme işlevlerine sahiptir.

Sadece bu değil, aynı zamanda kullanımı uygun olan dize biçimlendirme, sayı biçimlendirme vb. Gibi ortak genel amaçlı işlevler de sağlar.


1
katılıyorum, sugar.js burada daha fazla ilgiyi hak ediyor.
citykid

5

burada bir şeker-an örneği: haftaları gösteren bir takvim için son pazartesi değerine ihtiyacım vardı:

moment.js

var m = moment().subtract("days", 1).sod().day(1) // returns a "moment"

sugar.js

var d = Date.past("monday") // returns a js Date object

Daha çok şekeri tercih ediyorum ve birkaç ay sonra moment.js ile şimdi şeker.js'ye geçiyorum. daha net ve Javascripts'in Date sınıfıyla güzel bir şekilde bütünleşiyor.

Sugar.js bakınız için OP durumlarda her iki kütüphanelerini kapsamındadır http://sugarjs.com/dates


4

Bu js betiği çok güzel. Tek yapman gereken onu yürütmek. Tüm <time>etiketler göreceli tarihlerle değiştirilecek ve birkaç dakikada bir güncellenecektir, böylece göreli zaman her zaman güncel olacaktır.

http://timeago.yarp.com/


1
Bunun en iyi çözüm olduğunu düşünüyorum. Kütüphane çok aktif bir şekilde korunur, Resig'in koduna dayalıdır / esinlenmiştir, çok küçüktür, tonlarca yerelleştirmesi vardır, entegrasyonu önemsizdir.
John Bachir

4

Http://www.datejs.com/ kullanabilirsin gibi görünüyor

Ana sayfada tam olarak tarif ettiğiniz şeyi yapan bir örnekleri var!

DÜZENLEME: Aslında, sorunuzu kafamda tersine çevirdiğimi düşünüyorum. Her halükarda, gerçekten harika bir kütüphane olduğu için kontrol edebileceğinizi düşünüyorum!

DÜZENLEME x2: Başkalarının http://momentjs.com/ muhtemelen şu anda mevcut olan en iyi seçenek olduğunu söylediklerini tekrarlayacağım .

DÜZENLEME x3: Bir yıldan fazla bir süredir date.js kullanmadım. Tarihle ilgili tüm ihtiyaçlarım için yalnızca momentj'leri kullanıyorum.


Güzel kitap önerisi. Uluslararasılaşma kesinlikle bir artı.
Stephen

Date.js de benim ilk düşüncemdi, ancak onunla sayıdan biçime geçmenin bir yolunu görmüyorum - ancak belgelerde bir yerlerde gizlenmiş olabilir.
rampion

Date.js'nin ciddi hataları olduğu bilinmektedir ve üretim ortamlarında güvenilemez. Birçok çerçeve Date.js'den Moment.js'ye geçiyor
John Zabroski

Datejs'in linux üzerinde çalışmadığını zor yoldan öğrendim :(
fat fantasma
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.