Pustaka Javascript untuk pemformatan tanggal relatif yang ramah manusia [ditutup]

94

Saya ingin menampilkan beberapa tanggal sebagai relatif terhadap tanggal saat ini dalam format yang ramah manusia.

Contoh tanggal relatif ramah manusia:

  • 10 detik yang lalu
  • 20 menit dari sekarang
  • 1 hari yang lalu
  • 5 minggu lalu
  • 2 bulan yang lalu

Pada dasarnya dengan setia mempertahankan urutan besaran tertinggi (dan berdasarkan preferensi, hanya menggeser unit saat melewati 2 unit tersebut - 5 minggu, bukan 1 bulan).

Meskipun saya bisa hidup dengan perpustakaan yang kurang memiliki kendali dan bahkan tanggal yang lebih bersahabat seperti:

  • kemarin
  • besok
  • minggu lalu
  • beberapa menit yang lalu
  • dalam beberapa jam

Ada perpustakaan populer untuk ini?

rampion
sumber
Mengapa "1 hari yang lalu" lebih "ramah manusia" daripada sekadar menampilkan tanggal dan waktu sebenarnya?
RobG
5
@RobG Saya akan mengatakan ini lebih tentang menghindari beralih konteks misalnya di halaman yang sebagian besar teks dan sedang dibaca, konteks beralih ke misalnya mm / dd / yy dapat menyebabkan jeda. Dalam tabel data, menggunakan format itu mungkin lebih mudah dibaca. Ini juga tergantung pada apa yang pembaca perlu lakukan dengan tanggalnya misalnya apakah "ini terjadi n hari yang lalu" atau "ini terjadi sebelum 1/1/1972" dapat ditindaklanjuti atau sesuai dengan konteks pembaca.
wprl
Mungkin, tetapi membingungkan untuk melihat daftar peristiwa sebagai "Kemarin ... 3 hari yang lalu ... 10 / Mei ...". Saya masih perlu mengubah semuanya menjadi tanggal di kepala saya untuk mendapatkan gambaran kapan mereka terjadi. Tanggal singkat dan tepat, nilai "waktu yang lalu" bersifat percakapan, kurang presisi dan biasanya hanya berguna dengan tanggal terkait. Mungkin itu hanya aku, tapi mungkin juga tidak. :-)
RobG
6
Saya akan mengatakan itu tergantung pada konteksnya. Lagipula, Anda tidak akan mengatakan "Saya pergi memancing pada 17 Februari 2014" jika itu benar-benar kemarin. Masih banyak lagi otak yang berhenti di sana. Jenis teks ini sangat cocok untuk daftar kejadian terkini.
Simon Williams
2
@RobG Hanya kutu buku seperti kita yang berpikir seperti itu bukan orang normal.

Jawaban:

92

Sejak saya menulis jawaban ini, perpustakaan terkenal yang tersedia adalah moment.js .


Ada perpustakaan yang tersedia , tetapi itu mudah untuk diterapkan sendiri. Gunakan saja beberapa kondisi.

Asumsikan dateadalah Dateobjek yang dibuat untuk waktu yang ingin Anda bandingkan.

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

Anda perlu menyesuaikan ini untuk menangani tanggal-tanggal yang akan datang.

alex
sumber
9
Kemarin terjadi sebelum tengah malam terakhir, bukan antara 24 jam dan 48 jam yang lalu.
mxcl
@mmaclaurin Tambang tidak pernah dimaksudkan sebagai solusi lengkap, hanya penunjuk ke arah yang benar. Saya akan membuat catatan untuk memperbaruinya nanti, atau jika Anda mau, silakan edit jawabannya.
alex
Silakan lihat juga tanggal-fns ! Ini adalah pustaka yang bagus jika Anda ingin menjaga basis kode Anda tetap kecil, karena ia memiliki footprint yang jauh lebih rendah daripada momentjs!
mesqueeb
1
Saya mengubah kode ini untuk membuat getTimeAgofungsi gaya twitter gist.github.com/pomber/6195066a9258d1fb93bb59c206345b38
pomber
85

Saya menulis moment.js , perpustakaan tanggal yang melakukan ini. Ini tentang 5KB (2011) 52KB (2019), dan bekerja di browser dan di Node. Ini juga mungkin perpustakaan tanggal paling populer dan terkenal untuk JavaScript.

Ini mendukung timeago, pemformatan, parsing, kueri, manipulasi, i18n, dll.

Timeago (waktu relatif) untuk tanggal di masa lalu dilakukan dengan moment().fromNow(). Misalnya untuk menampilkan 1 Januari 2019 dalam format timeago:

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

String timeago dapat disesuaikan dengan moment.updateLocale(), sehingga Anda dapat mengubahnya sesuai keinginan Anda.

Batasnya bukanlah apa yang diminta pertanyaan ("5 minggu" vs. "1 bulan"), tetapi ini didokumentasikan sebagai string mana yang digunakan untuk rentang waktu apa.

kayu kayu
sumber
1
Kudos untuk membuatnya berfungsi di browser dan node !!!!
wprl
49
ha pembaruan ukuran itu!
Askdesigners
1
Silakan lihat juga tanggal-fns ! Ini adalah pustaka yang bagus jika Anda ingin menjaga basis kode Anda tetap kecil, karena ia memiliki footprint yang jauh lebih rendah daripada momentjs!
mesqueeb
Meski perpustakaan ini bagus, jawabannya tidak termasuk penjelasan tentang cara memformat angka dengan cara yang ramah manusia menggunakannya
Code Whisperer
16

Ini sesuatu dari John Resig - http://ejohn.org/blog/javascript-pretty-date/

EDIT (6/27/2014): Menindaklanjuti komentar dari Sumurai8 - meskipun halaman tertaut masih berfungsi, berikut adalah kutipan untukpretty.js ditautkan dari artikel di atas:

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

Pemakaian:

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

Kutipan dari artikel tentang penggunaan:

Contoh Penggunaan

Dalam contoh berikut saya membuat semua jangkar di situs, yang memiliki judul dengan tanggal di dalamnya, memiliki tanggal yang cantik sebagai teks dalamnya. Selain itu, saya terus memperbarui link setiap 5 detik setelah halaman dimuat.

Dengan JavaScript:

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

Dengan jQuery:

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

Faiz: Membuat beberapa perubahan pada kode asli, perbaikan bug, dan peningkatan.

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;
}
Hari Pachuveetil
sumber
1
Hai Floyd, saya telah menambahkan beberapa perubahan (perbaikan bug, peningkatan) pada jawaban Anda. Harap Anda tidak keberatan ..
Faiz
Bagus! Namun tidak berfungsi dengan tipe numerik timestamp, mungkin perlu filter yang lebih baik seperti if (typeof time == 'string') {time = time.replace (/ - / g, "/").replace(/[TZ]/ g, "")); }
Arthur Araújo
15

sugar.js memiliki fungsi format tanggal yang bagus.

Tidak hanya itu, ia juga menyediakan fungsi tujuan umum umum seperti pemformatan string, pemformatan angka, dll. Yang nyaman digunakan.

Hendy Irawan
sumber
1
setuju, sugar.js layak mendapat perhatian lebih di sini.
citykid
5

di sini contoh gula vs momen: untuk kalender yang menampilkan minggu, saya membutuhkan nilai senin terakhir:

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

Saya lebih suka gula dan setelah beberapa bulan dengan moment.js sekarang beralih ke sugar.js. itu lebih jelas dan terintegrasi dengan baik dengan kelas Tanggal Javascripts.

Kasus OP dicakup oleh kedua libs, untuk sugar.js lihat http://sugarjs.com/dates

citykid
sumber
4

Skrip js ini sangat bagus. Yang harus Anda lakukan adalah menjalankannya. Semua <time>tag akan diubah ke tanggal relatif dan diperbarui setiap beberapa menit, sehingga waktu relatif akan selalu diperbarui.

http://timeago.yarp.com/

boreq
sumber
1
Saya rasa ini adalah solusi terbaik. Pustaka ini dipelihara dengan sangat aktif, berdasarkan / terinspirasi oleh kode Resig, sangat kecil, memiliki banyak pelokalan, mudah untuk diintegrasikan.
John Bachir
4

Sepertinya Anda bisa menggunakan http://www.datejs.com/

Mereka memiliki contoh di halaman utama yang melakukan persis seperti yang Anda gambarkan!

EDIT: Sebenarnya, saya pikir saya membalikkan pertanyaan Anda di kepala saya. Bagaimanapun, saya pikir Anda bisa memeriksanya karena ini adalah perpustakaan yang sangat bagus!

EDIT x2: Saya akan mengulangi apa yang dikatakan orang lain. Http://momentjs.com/ mungkin adalah pilihan terbaik yang tersedia saat ini.

EDIT x3: Saya belum pernah menggunakan date.js selama lebih dari setahun. Saya secara eksklusif menggunakan momentjs untuk semua kebutuhan terkait tanggal saya.

RoboKozo
sumber
Saran lib bagus. Internasionalisasi jelas merupakan nilai tambah.
Stephen
Date.js adalah pemikiran pertama saya juga, tetapi saya tidak melihat cara untuk beralih dari angka ke format dengannya - meskipun itu mungkin tersembunyi di dokumen di suatu tempat.
rampion
Date.js dikenal memiliki bug yang serius, dan tidak dapat dipercaya di lingkungan produksi. Banyak kerangka kerja yang beralih dari Date.js ke Moment.js
John Zabroski
Saya belajar dari pengalaman pahit bahwa datejs tidak berfungsi di linux :(
fat fantasma