ไลบรารี Javascript สำหรับการจัดรูปแบบวันที่ที่สัมพันธ์กับมนุษย์ [ปิด]


97

ฉันต้องการแสดงวันที่บางวันที่สัมพันธ์กับวันที่ปัจจุบันในรูปแบบที่เป็นมิตรกับมนุษย์

ตัวอย่างวันที่ญาติที่เป็นมิตรกับมนุษย์:

  • 10 วินาทีที่แล้ว
  • 20 นาทีจากนี้
  • 1 วันที่ผ่านมา
  • 5 สัปดาห์ที่ผ่านมา
  • 2 เดือนที่แล้ว

โดยพื้นฐานแล้วจะรักษาลำดับความสำคัญสูงสุดไว้อย่างซื่อสัตย์ (และตามความต้องการเฉพาะการขยับขึ้นหน่วยเมื่อผ่าน 2 หน่วย - 5 สัปดาห์แทนที่จะเป็น 1 เดือน)

แม้ว่าฉันจะสามารถอยู่กับห้องสมุดที่มีการควบคุมน้อยลงและเป็นกันเองมากขึ้นเช่น:

  • เมื่อวานนี้
  • พรุ่งนี้
  • อาทิตย์ที่แล้ว
  • ไม่กี่นาทีที่ผ่านมา
  • ในสองสามชั่วโมง

ห้องสมุดยอดนิยมสำหรับสิ่งนี้หรือไม่?


เหตุใด "1 วันที่ผ่านมา" จึง "เป็นมิตรกับมนุษย์" มากกว่าการนำเสนอวันและเวลาจริง
RobG

5
@RobG ฉันจะบอกว่ามันเป็นเรื่องเกี่ยวกับการหลีกเลี่ยงการสลับบริบทเช่นในหน้าที่ส่วนใหญ่เป็นข้อความและกำลังอ่านอยู่การเปลี่ยนบริบทเป็นเช่น mm / dd / yy อาจทำให้หยุดชั่วคราวได้ ในตารางข้อมูลการใช้รูปแบบนั้นอาจอ่านได้ง่ายกว่า นอกจากนี้ยังขึ้นอยู่กับสิ่งที่ผู้อ่านต้องดำเนินการกับวันที่เช่น "สิ่งนี้เกิดขึ้นเมื่อไม่กี่วันก่อน" หรือ "สิ่งนี้เกิดขึ้นก่อน 1/1/1972" สามารถดำเนินการได้หรือเหมาะสมกับบริบทของผู้อ่าน
wprl

บางทีอาจจะสับสนเมื่อเห็นรายการเหตุการณ์เป็น "เมื่อวาน ... 3 วันที่แล้ว ... 10 / พฤษภาคม ... " ฉันยังคงต้องแปลงมันทั้งหมดเป็นวันที่ในหัวของฉันเพื่อให้ได้ภาพที่เกิดขึ้น วันที่มีความกระชับและแม่นยำค่า "เวลาที่แล้ว" เป็นการสนทนาขาดความแม่นยำและโดยปกติจะเป็นประโยชน์เฉพาะกับวันที่ที่เกี่ยวข้องเท่านั้น บางทีนั่นอาจเป็นแค่ฉัน แต่อาจจะไม่ใช่ :-)
RobG

6
ฉันจะบอกว่ามันขึ้นอยู่กับบริบท ท้ายที่สุดคุณจะไม่พูดว่า "ฉันไปตกปลาเมื่อวันที่ 17 กุมภาพันธ์ 2014" ถ้านั่นคือเมื่อวานนี้จริงๆ สมองหยุดอยู่ที่นั่นอีกมากมาย ข้อความประเภทนี้เหมาะสำหรับรายการเหตุการณ์ล่าสุด
Simon Williams

2
@RobG เด็กเนิร์ดอย่างเราเท่านั้นที่คิดแบบนั้นไม่ใช่คนปกติ

คำตอบ:


94

ตั้งแต่ผมเขียนคำตอบนี้ห้องสมุดที่รู้จักกันดีมีอยู่moment.js


มีไลบรารีให้บริการแต่การใช้งานด้วยตัวเองเป็นเรื่องเล็กน้อย เพียงใช้เงื่อนไขเพียงหยิบมือ

สมมติdateเป็นDateวัตถุที่สร้างอินสแตนซ์สำหรับเวลาที่คุณต้องการเปรียบเทียบ

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

คุณจะต้องปรับเปลี่ยนสิ่งนี้เพื่อรองรับวันที่ในอนาคต


9
เมื่อวานนี้ก่อนเที่ยงคืนสุดท้ายไม่ใช่ระหว่าง 24 ชั่วโมงถึง 48 ชั่วโมงที่แล้ว
mxcl

@mmaclaurin Mine ไม่เคยหมายถึงการแก้ปัญหาที่สมบูรณ์เพียงแค่ชี้ไปในทิศทางที่ถูกต้อง ฉันจะบันทึกเพื่ออัปเดตในภายหลังหรือหากคุณต้องการโปรดแก้ไขคำตอบได้ตามต้องการ
alex

โปรดดูdate-fns ด้วย ! เป็นไลบรารีที่ยอดเยี่ยมหากคุณต้องการให้ฐานรหัสของคุณมีขนาดเล็กเพราะมันมีรอยเท้าต่ำกว่าช่วงเวลามาก
mesqueeb

1
ฉันเปลี่ยนรหัสนี้เพื่อสร้างgetTimeAgoฟังก์ชันสไตล์ Twitter gist.github.com/pomber/6195066a9258d1fb93bb59c206345b38
pomber

88

ฉันเขียนmoment.jsซึ่งเป็นไลบรารีวันที่ที่ทำสิ่งนี้ ประมาณ5KB (2011) 52KB (2019) และใช้งานได้ในเบราว์เซอร์และในโหนด นอกจากนี้ยังอาจเป็นไลบรารีวันที่ที่เป็นที่นิยมและมีชื่อเสียงที่สุดสำหรับ JavaScript

รองรับ timeago, การจัดรูปแบบ, การแยกวิเคราะห์, การสืบค้น, การจัดการ, i18n ฯลฯ

Timeago (เวลาสัมพัทธ์) สำหรับวันที่ในอดีตจะทำด้วยmoment().fromNow(). ตัวอย่างเช่นหากต้องการแสดงวันที่ 1 มกราคม 2019 ในรูปแบบ timeago:

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

สตริง timeago สามารถปรับแต่งได้ด้วยmoment.updateLocale()ดังนั้นคุณจึงสามารถเปลี่ยนได้ตามความเหมาะสม

การตัดไม่ได้เป็นสิ่งที่คำถามขอ ("5 สัปดาห์" เทียบกับ "1 เดือน") แต่มีการบันทึกไว้ว่าสตริงใดที่ใช้สำหรับช่วงเวลาใด


1
ความรุ่งโรจน์ในการทำให้มันทำงานในเบราว์เซอร์และโหนด !!!!
wprl

52
ฮาขนาดนั้นอัพเดท!
Askdesigners

1
โปรดดูdate-fns ด้วย ! เป็นไลบรารีที่ยอดเยี่ยมหากคุณต้องการให้ฐานรหัสของคุณมีขนาดเล็กเพราะมันมีรอยเท้าต่ำกว่าช่วงเวลามาก
mesqueeb

ดีเท่าที่ห้องสมุดนี้คือคำตอบไม่มีคำอธิบายเกี่ยวกับวิธีจัดรูปแบบตัวเลขในลักษณะที่เป็นมิตรกับมนุษย์โดยใช้
Code Whisperer

คุณจะอัปเดตด้วยการ "เลิกใช้งาน" ด้วยหรือไม่? momentjs.com/docs/#/-project-status
Juan De la Cruz

17

นี่คือบางสิ่งจาก John Resig - http://ejohn.org/blog/javascript-pretty-date/

แก้ไข (27/6/2557): ติดตามความคิดเห็นจากSumurai8 - แม้ว่าหน้าที่เชื่อมโยงจะยังใช้งานได้ แต่นี่คือข้อความที่ตัดตอนมาสำหรับpretty.jsลิงก์จากบทความด้านบน:

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

การใช้งาน:

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

ตัดตอนมาจากบทความเกี่ยวกับการใช้งาน:

ตัวอย่างการใช้งาน

ในตัวอย่างต่อไปนี้ฉันสร้างจุดยึดทั้งหมดบนไซต์ซึ่งมีชื่อเรื่องพร้อมวันที่อยู่ในนั้นมีวันที่ที่สวยงามเป็นข้อความด้านใน นอกจากนี้ฉันยังคงอัปเดตลิงก์ทุก ๆ 5 วินาทีหลังจากที่โหลดเพจแล้ว

ด้วย 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);

ด้วย jQuery:

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

Faiz: ทำการเปลี่ยนแปลงโค้ดดั้งเดิมแก้ไขข้อบกพร่องและปรับปรุง

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
สวัสดี Floyd ฉันได้เพิ่มการเปลี่ยนแปลงบางอย่าง (แก้ไขข้อบกพร่องการปรับปรุง) ให้กับคำตอบของคุณ หวังว่าคงไม่เป็นไร ..
Faiz

สิ่งที่ดี! แต่ใช้ไม่ได้กับประเภทตัวเลขเวลาประทับอาจต้องใช้ตัวกรองที่ดีกว่าเช่น if (typeof time == 'string') {time = time.replace (/ - / g, "/").replace(/[TZ]/ ก, "")); }
Arthur Araújo

กรุณาบัญชีสำหรับวันที่ในอนาคตอย่างไร? ชอบ 2 วันจากนี้
Ikenna Emman

15

sugar.jsมีฟังก์ชันการจัดรูปแบบวันที่ที่ยอดเยี่ยม

ไม่เพียงแค่นั้นยังมีฟังก์ชันสำหรับวัตถุประสงค์ทั่วไปเช่นการจัดรูปแบบสตริงการจัดรูปแบบตัวเลข ฯลฯ ที่ใช้งานได้สะดวก


1
เห็นด้วย sugar.js สมควรได้รับความสนใจมากกว่าที่นี่
citykid

5

นี่คือตัวอย่างของน้ำตาลเทียบกับช่วงเวลา: สำหรับปฏิทินที่แสดงสัปดาห์ฉันต้องการค่าวันจันทร์สุดท้าย:

moment.js

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

น้ำตาล js

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

ฉันชอบน้ำตาลมากและหลังจากผ่านไปหลายเดือนด้วยช่วงเวลา js ตอนนี้เปลี่ยนเป็น sugar.js มีความชัดเจนและรวมเข้ากับคลาส Date ของ Javascripts ได้เป็นอย่างดี

กรณี OP ครอบคลุมทั้ง libs สำหรับ sugar.js โปรดดูที่http://sugarjs.com/dates


4

สคริปต์ js นี้ดีมาก สิ่งที่คุณต้องทำคือดำเนินการ <time>แท็กทั้งหมดจะเปลี่ยนเป็นวันที่ที่สัมพันธ์กันและอัปเดตทุกๆสองสามนาทีดังนั้นเวลาที่สัมพันธ์กันจะเป็นปัจจุบันเสมอ

http://timeago.yarp.com/


1
ฉันคิดว่านี่เป็นทางออกที่ดีที่สุด ห้องสมุดได้รับการดูแลอย่างแข็งขันโดยอิงจาก / ได้รับแรงบันดาลใจจากรหัสของ Resig ซึ่งมีขนาดเล็กมากมีการแปลเป็นภาษาท้องถิ่นจำนวนมากการรวมเข้าด้วยกันเป็นเรื่องเล็กน้อย
John Bachir

4

ดูเหมือนว่าคุณสามารถใช้http://www.datejs.com/

พวกเขามีตัวอย่างในหน้าหลักที่ตรงตามที่คุณอธิบาย!

แก้ไข: ที่จริงฉันคิดว่าฉันย้อนคำถามของคุณในหัวของฉัน ไม่ว่าในกรณีใดฉันคิดว่าคุณสามารถตรวจสอบได้เนื่องจากเป็นห้องสมุดที่ยอดเยี่ยมจริงๆ!

แก้ไข x2: ฉันจะสะท้อนสิ่งที่คนอื่นพูดhttp://momentjs.com/น่าจะเป็นทางเลือกที่ดีที่สุดในตอนนี้

แก้ไข x3: ฉันไม่ได้ใช้ date.js มานานกว่าหนึ่งปี ฉันใช้เฉพาะช่วงเวลาสำหรับความต้องการที่เกี่ยวข้องกับวันที่ทั้งหมดของฉัน


ข้อเสนอแนะที่ดี lib ความเป็นสากลแน่นอนเป็นบวก
Stephen

Date.js เป็นความคิดแรกของฉันเช่นกัน แต่ฉันไม่เห็นวิธีเปลี่ยนจากตัวเลขเป็นรูปแบบใด ๆ แม้ว่ามันอาจจะซ่อนอยู่ในเอกสารที่ไหนสักแห่ง
rampion

Date.js เป็นที่ทราบกันดีว่ามีข้อบกพร่องร้ายแรงและไม่สามารถเชื่อถือได้ในสภาพแวดล้อมการใช้งานจริง เฟรมเวิร์กจำนวนมากกำลังเปลี่ยนจาก Date.js เป็น Moment.js
John Zabroski

ฉันเรียนรู้วิธีที่ยากที่ datejs ไม่ทำงานบน linux :(
fat fantasma
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.