Bagaimana jika Anda ingin menghitung waktu relatif dari sekarang ke Masa Depan?
Jhonny D. Cano -Leftware-
2
moment.js adalah parsing library tanggal yang sangat bagus .. Anda dapat mempertimbangkan untuk menggunakannya (sisi server atau sisi klien), tergantung pada kebutuhan Anda. hanya fyi karena tidak ada yang menyebutkannya di sini
Aku benci konstanta seperti itu dengan hasrat. Apakah ini terlihat salah bagi siapa pun? Thread.Sleep(1 * MINUTE)? Karena itu salah dengan faktor 1000.
Roman Starkov
31
const int SECOND = 1;Jadi aneh satu detik adalah satu detik.
seriousdev
62
Jenis kode ini hampir tidak mungkin dilokalisasi. Jika aplikasi Anda hanya perlu tetap dalam bahasa Inggris, maka baiklah. Tetapi jika Anda melompat ke bahasa lain, Anda akan membenci diri sendiri karena melakukan logika seperti ini. Asal tahu saja ...
Nik Reiman
73
Saya pikir jika konstanta diganti untuk menggambarkan secara akurat nilai yang ada di dalamnya, akan lebih mudah untuk dipahami. Jadi SecondsPerMinute = 60; MinutesPerHour = 60; SecondsPerHour = MinutesPerHour * SecondsPerHour; dll. Hanya menyebutnya MINUTE = 60 tidak memungkinkan pembaca menentukan nilainya.
slolife
14
Mengapa tidak ada orang (kecuali Joe) yang peduli dengan nilai 'Kemarin' atau 'hari yang lalu' yang salah ??? Kemarin bukan perhitungan jam, tapi perhitungan hari ke hari. Jadi ya, ini adalah kode yang salah setidaknya dalam dua kasus yang sering.
Seb, Jika Anda menonaktifkan Javascript, maka string yang semula Anda masukkan di antara tag abbr ditampilkan. Biasanya, ini hanya tanggal atau waktu dalam format apa pun yang Anda inginkan. Timeago terdegradasi dengan anggun. Itu tidak menjadi jauh lebih sederhana.
Heh, terima kasih Rob. Tidak apa-apa. Ini hampir tidak terlihat, terutama ketika hanya satu perubahan nomor selama transisi, meskipun halaman SO memiliki banyak cap waktu. Saya akan berpikir dia akan setidaknya menghargai manfaat dari caching halaman, meskipun ia memilih untuk menghindari pembaruan otomatis. Saya yakin Jeff bisa memberikan umpan balik untuk meningkatkan plugin juga. Saya senang mengetahui situs seperti arstechnica.com menggunakannya.
Ryan McGeary
19
@Rob Fonseca-Ensor - sekarang membuat saya menangis juga. Bagaimana cara pembaruan sekali per menit, untuk menampilkan informasi yang akurat, dengan cara apa pun yang terkait dengan teks yang berkedip sekali dalam satu detik?
Daniel Earwicker
25
Pertanyaannya adalah tentang C #, saya gagal melihat bagaimana plugin jQuery relevan.
"<48 * 60 * 60s" adalah definisi yang agak tidak konvensional untuk "kemarin". Jika jam 9 pagi pada hari Rabu, apakah Anda benar-benar menganggap jam 9:01 pagi pada hari Senin sebagai "kemarin". Saya akan berpikir algoritma untuk kemarin atau "n hari yang lalu" harus dipertimbangkan sebelum / sesudah tengah malam.
Joe
139
Compiler biasanya cukup baik di ekspresi konstan pra-menghitung, seperti 24 * 60 * 60, sehingga Anda langsung dapat menggunakan mereka sebagai gantinya menghitung sendiri menjadi 86.400 dan menempatkan ekspresi asli dalam komentar
zvolkov
11
@ bzlm Saya pikir saya lakukan untuk proyek yang sedang saya kerjakan. Motivasi saya di sini adalah untuk mengingatkan orang lain bahwa minggu dihilangkan dari contoh kode ini. Mengenai cara melakukan itu, bagiku itu tampak cukup lurus.
jray
9
Saya pikir cara yang baik untuk meningkatkan algoritma adalah menampilkan 2 unit seperti "2 bulan 21 hari yang lalu", "1 jam 40 menit yang lalu" untuk meningkatkan akurasi.
Evgeny Levin
5
@ Jeffy, Anda melewatkan perhitungan untuk tahun kabisat dan cek terkait
Saboor Awan
92
publicstaticstringRelativeDate(DateTime theDate){Dictionary<long,string> thresholds =newDictionary<long,string>();int minute =60;int hour =60* minute;int day =24* hour;
thresholds.Add(60,"{0} seconds ago");
thresholds.Add(minute *2,"a minute ago");
thresholds.Add(45* minute,"{0} minutes ago");
thresholds.Add(120* minute,"an hour ago");
thresholds.Add(day,"{0} hours ago");
thresholds.Add(day *2,"yesterday");
thresholds.Add(day *30,"{0} days ago");
thresholds.Add(day *365,"{0} months ago");
thresholds.Add(long.MaxValue,"{0} years ago");long since =(DateTime.Now.Ticks- theDate.Ticks)/10000000;foreach(long threshold in thresholds.Keys){if(since < threshold){TimeSpan t =newTimeSpan((DateTime.Now.Ticks- theDate.Ticks));returnstring.Format(thresholds[threshold],(t.Days>365? t.Days/365:(t.Days>0? t.Days:(t.Hours>0? t.Hours:(t.Minutes>0? t.Minutes:(t.Seconds>0? t.Seconds:0))))).ToString());}}return"";}
Saya lebih suka versi ini karena keringkasannya, dan kemampuan untuk menambahkan titik centang baru. Ini bisa dienkapsulasi dengan Latest()ekstensi ke Timespan alih-alih 1 liner yang panjang itu, tetapi demi singkatnya dalam posting, ini bisa dilakukan.
Ini memperbaiki satu jam yang lalu, 1 jam yang lalu, dengan menyediakan satu jam sampai 2 jam telah berlalu
Saya mendapatkan segala macam masalah menggunakan fungsi ini, misalnya jika Anda mengejek 'theDate = DateTime.Now.AddMinutes (-40);' Saya mendapatkan '40 jam yang lalu ', tetapi dengan respons refactormycode Michael, hasilnya benar pada '40 menit yang lalu'?
GONeale
saya pikir Anda kehilangan nol, coba: lama sejak = (DateTime.Now.Ticks - theDate.Ticks) / 10000000;
robnardo
8
Hmm, sementara kode ini bisa berfungsi, itu tidak benar dan tidak valid untuk menganggap bahwa urutan tombol dalam Kamus akan berada dalam urutan tertentu. Kamus menggunakan Object.GetHashCode () yang tidak mengembalikan panjang tapi int !. Jika Anda ingin ini diurutkan maka Anda harus menggunakan SortedList <long, string>. Apa yang salah dengan ambang yang dievaluasi dalam satu set if / else jika /.../ else? Anda mendapatkan jumlah perbandingan yang sama. FYI hash untuk long.MaxValue ternyata sama dengan int.MinValue!
CodeMonkeyKing
OP lupa t. Hari> 30? t.Days / 30:
Lars Holm Jensen
Untuk memperbaiki masalah yang disebutkan oleh @CodeMonkeyKing, Anda bisa menggunakan SortedDictionaryalih - alih polos Dictionary: Penggunaannya sama, tetapi memastikan bahwa kunci diurutkan. Tetapi meskipun demikian, algoritmanya memiliki kekurangan, karena RelativeDate(DateTime.Now.AddMonths(-3).AddDays(-3))mengembalikan "95 bulan yang lalu" , terlepas dari jenis kamus yang Anda gunakan, yang tidak benar (harus mengembalikan "3 bulan lalu" atau "4 bulan lalu" tergantung pada ambang mana Anda kembali menggunakan) - bahkan jika -3 tidak membuat tanggal dalam satu tahun terakhir (saya telah menguji ini pada bulan Desember, jadi dalam kasus ini seharusnya tidak terjadi).
Matt
71
Berikut penulisan ulang dari Jeffs Script untuk PHP:
staticreadonlySortedList<double,Func<TimeSpan,string>> offsets =newSortedList<double,Func<TimeSpan,string>>{{0.75, _ =>"less than a minute"},{1.5, _ =>"about a minute"},{45, x => $"{x.TotalMinutes:F0} minutes"},{90, x =>"about an hour"},{1440, x => $"about {x.TotalHours:F0} hours"},{2880, x =>"a day"},{43200, x => $"{x.TotalDays:F0} days"},{86400, x =>"about a month"},{525600, x => $"{x.TotalDays / 30:F0} months"},{1051200, x =>"about a year"},{double.MaxValue, x => $"{x.TotalDays / 365:F0} years"}};publicstaticstringToRelativeDate(thisDateTime input){TimeSpan x =DateTime.Now- input;stringSuffix= x.TotalMinutes>0?" ago":" from now";
x =newTimeSpan(Math.Abs(x.Ticks));return offsets.First(n => x.TotalMinutes< n.Key).Value(x)+Suffix;}
ini IMO yang sangat bagus :) Ini juga bisa di refactored sebagai metode ekstensi? dapatkah kamus menjadi statis sehingga hanya dibuat sekali dan direferensikan sejak saat itu?
Anda mungkin ingin menarik kamus itu ke bidang sehingga Anda mengurangi instantiasi dan churn GC. Anda harus berubah Func<string>menjadi Func<double>.
Drew Noakes
49
Berikut ini adalah implementasi yang saya tambahkan sebagai metode ekstensi ke kelas DateTime yang menangani tanggal di masa depan dan masa lalu dan menyediakan opsi perkiraan yang memungkinkan Anda menentukan tingkat detail yang Anda cari ("3 jam yang lalu" vs "3 jam, 23 menit, 12 detik yang lalu "):
usingSystem.Text;/// <summary>/// Compares a supplied date to the current date and generates a friendly English /// comparison ("5 days ago", "5 days from now")/// </summary>/// <param name="date">The date to convert</param>/// <param name="approximate">When off, calculate timespan down to the second./// When on, approximate to the largest round unit of time.</param>/// <returns></returns>publicstaticstringToRelativeDateString(thisDateTimevalue,bool approximate){StringBuilder sb =newStringBuilder();string suffix =(value>DateTime.Now)?" from now":" ago";TimeSpan timeSpan =newTimeSpan(Math.Abs(DateTime.Now.Subtract(value).Ticks));if(timeSpan.Days>0){
sb.AppendFormat("{0} {1}", timeSpan.Days,(timeSpan.Days>1)?"days":"day");if(approximate)return sb.ToString()+ suffix;}if(timeSpan.Hours>0){
sb.AppendFormat("{0}{1} {2}",(sb.Length>0)?", ":string.Empty,
timeSpan.Hours,(timeSpan.Hours>1)?"hours":"hour");if(approximate)return sb.ToString()+ suffix;}if(timeSpan.Minutes>0){
sb.AppendFormat("{0}{1} {2}",(sb.Length>0)?", ":string.Empty,
timeSpan.Minutes,(timeSpan.Minutes>1)?"minutes":"minute");if(approximate)return sb.ToString()+ suffix;}if(timeSpan.Seconds>0){
sb.AppendFormat("{0}{1} {2}",(sb.Length>0)?", ":string.Empty,
timeSpan.Seconds,(timeSpan.Seconds>1)?"seconds":"second");if(approximate)return sb.ToString()+ suffix;}if(sb.Length==0)return"right now";
sb.Append(suffix);return sb.ToString();}
catatan ramah: Pada .net 4.5 atau di atas tidak menginstal Humanizer lengkap ... hanya instal Humanizer.Core bagian dari itu .. menyebabkan paket bahasa lain tidak didukung pada versi ini
Ahmad
Sangat bermanfaat! Jawaban ini harus jauh lebih tinggi dalam daftar ini. Jika saya memiliki 100 suara, saya akan memberikan ini. Ternyata (berasal dari JS-land), mencari paket ini tidak mudah.
kumarharsh
29
@ Jeff
IMHO Anda tampaknya agak panjang. Namun tampaknya sedikit lebih kuat dengan dukungan untuk "kemarin" dan "tahun". Tetapi dalam pengalaman saya ketika ini digunakan orang tersebut kemungkinan besar akan melihat konten dalam 30 hari pertama. Hanya orang-orang yang benar-benar hardcore yang datang setelah itu. Jadi itu sebabnya saya biasanya memilih untuk menjaga ini pendek dan sederhana.
Ini adalah metode yang saya gunakan saat ini di salah satu situs web saya. Ini hanya mengembalikan hari, jam, waktu relatif. Dan kemudian pengguna harus menampar "lalu" di output.
Beberapa tahun terlambat ke pesta, tetapi saya memiliki persyaratan untuk melakukan ini untuk tanggal masa lalu dan masa depan, jadi saya menggabungkan Jeff dan Vincent ke dalam ini. Ini ekstravaganza ternarytastic! :)
publicstaticclassDateTimeHelper{privateconstint SECOND =1;privateconstint MINUTE =60* SECOND;privateconstint HOUR =60* MINUTE;privateconstint DAY =24* HOUR;privateconstint MONTH =30* DAY;/// <summary>/// Returns a friendly version of the provided DateTime, relative to now. E.g.: "2 days ago", or "in 6 months"./// </summary>/// <param name="dateTime">The DateTime to compare to Now</param>/// <returns>A friendly string</returns>publicstaticstringGetFriendlyRelativeTime(DateTime dateTime){if(DateTime.UtcNow.Ticks== dateTime.Ticks){return"Right now!";}bool isFuture =(DateTime.UtcNow.Ticks< dateTime.Ticks);var ts =DateTime.UtcNow.Ticks< dateTime.Ticks?newTimeSpan(dateTime.Ticks-DateTime.UtcNow.Ticks):newTimeSpan(DateTime.UtcNow.Ticks- dateTime.Ticks);double delta = ts.TotalSeconds;if(delta <1* MINUTE){return isFuture ?"in "+(ts.Seconds==1?"one second": ts.Seconds+" seconds"): ts.Seconds==1?"one second ago": ts.Seconds+" seconds ago";}if(delta <2* MINUTE){return isFuture ?"in a minute":"a minute ago";}if(delta <45* MINUTE){return isFuture ?"in "+ ts.Minutes+" minutes": ts.Minutes+" minutes ago";}if(delta <90* MINUTE){return isFuture ?"in an hour":"an hour ago";}if(delta <24* HOUR){return isFuture ?"in "+ ts.Hours+" hours": ts.Hours+" hours ago";}if(delta <48* HOUR){return isFuture ?"tomorrow":"yesterday";}if(delta <30* DAY){return isFuture ?"in "+ ts.Days+" days": ts.Days+" days ago";}if(delta <12* MONTH){int months =Convert.ToInt32(Math.Floor((double)ts.Days/30));return isFuture ?"in "+(months <=1?"one month": months +" months"): months <=1?"one month ago": months +" months ago";}else{int years =Convert.ToInt32(Math.Floor((double)ts.Days/365));return isFuture ?"in "+(years <=1?"one year": years +" years"): years <=1?"one year ago": years +" years ago";}}}
Mengingat dunia dan suaminya tampak memposting contoh kode, inilah yang saya tulis beberapa waktu lalu, berdasarkan pada beberapa jawaban ini.
Saya memiliki kebutuhan khusus agar kode ini dapat dilokalisasi. Jadi saya punya dua kelas - Grammar, yang menentukan istilah yang dapat di-lokalisasi, dan FuzzyDateExtensions, yang memiliki banyak metode ekstensi. Saya tidak perlu berurusan dengan datetimes masa depan, jadi tidak ada upaya yang dilakukan untuk menangani mereka dengan kode ini.
Saya telah meninggalkan beberapa XMLdoc di sumbernya, tetapi menghapus sebagian besar (di mana mereka akan jelas) demi singkatnya. Saya juga tidak menyertakan setiap anggota kelas di sini:
publicclassGrammar{/// <summary> Gets or sets the term for "just now". </summary>publicstringJustNow{get;set;}/// <summary> Gets or sets the term for "X minutes ago". </summary>/// <remarks>/// This is a <see cref="String.Format"/> pattern, where <c>{0}</c>/// is the number of minutes./// </remarks>publicstringMinutesAgo{get;set;}publicstringOneHourAgo{get;set;}publicstringHoursAgo{get;set;}publicstringYesterday{get;set;}publicstringDaysAgo{get;set;}publicstringLastMonth{get;set;}publicstringMonthsAgo{get;set;}publicstringLastYear{get;set;}publicstringYearsAgo{get;set;}/// <summary> Gets or sets the term for "ages ago". </summary>publicstringAgesAgo{get;set;}/// <summary>/// Gets or sets the threshold beyond which the fuzzy date should be/// considered "ages ago"./// </summary>publicTimeSpanAgesAgoThreshold{get;set;}/// <summary>/// Initialises a new <see cref="Grammar"/> instance with the/// specified properties./// </summary>privatevoidInitialise(string justNow,string minutesAgo,string oneHourAgo,string hoursAgo,string yesterday,string daysAgo,string lastMonth,string monthsAgo,string lastYear,string yearsAgo,string agesAgo,TimeSpan agesAgoThreshold){...}}
Salah satu hal kunci yang saya ingin mencapai, serta lokalisasi, adalah bahwa "hari ini" hanya akan berarti "hari kalender ini", sehingga IsToday, IsThisMonth, IsThisYearmetode terlihat seperti ini:
Saya pikir saya akan mencoba ini menggunakan kelas dan polimorfisme. Saya memiliki iterasi sebelumnya yang menggunakan sub-klasifikasi yang akhirnya memiliki terlalu banyak overhead. Saya telah beralih ke model objek properti delegasi / publik yang lebih fleksibel yang jauh lebih baik. Kode saya sedikit lebih akurat, saya berharap saya bisa menemukan cara yang lebih baik untuk menghasilkan "bulan lalu" yang sepertinya tidak terlalu direkayasa.
Saya pikir saya masih akan tetap dengan kasing Jeff jika-maka karena lebih sedikit kode dan lebih sederhana (itu pasti lebih mudah untuk memastikan itu akan berfungsi seperti yang diharapkan).
Untuk kode di bawah ini PrintRelativeTime.GetRelativeTimeMessage (TimeSpan lalu) mengembalikan pesan waktu relatif (misalnya "kemarin").
publicclassRelativeTimeRange:IComparable{publicTimeSpanUpperBound{get;set;}publicdelegatestringRelativeTimeTextDelegate(TimeSpan timeDelta);publicRelativeTimeTextDelegateMessageCreator{get;set;}publicintCompareTo(object obj){if(!(obj isRelativeTimeRange)){return1;}// note that this sorts in reverse order to the way you'd expect, // this saves having to reverse a list laterreturn(obj asRelativeTimeRange).UpperBound.CompareTo(UpperBound);}}publicclassPrintRelativeTime{privatestaticList<RelativeTimeRange> timeRanges;staticPrintRelativeTime(){
timeRanges =newList<RelativeTimeRange>{newRelativeTimeRange{UpperBound=TimeSpan.FromSeconds(1),MessageCreator=(delta)=>{return"one second ago";}},newRelativeTimeRange{UpperBound=TimeSpan.FromSeconds(60),MessageCreator=(delta)=>{return delta.Seconds+" seconds ago";}},newRelativeTimeRange{UpperBound=TimeSpan.FromMinutes(2),MessageCreator=(delta)=>{return"one minute ago";}},newRelativeTimeRange{UpperBound=TimeSpan.FromMinutes(60),MessageCreator=(delta)=>{return delta.Minutes+" minutes ago";}},newRelativeTimeRange{UpperBound=TimeSpan.FromHours(2),MessageCreator=(delta)=>{return"one hour ago";}},newRelativeTimeRange{UpperBound=TimeSpan.FromHours(24),MessageCreator=(delta)=>{return delta.Hours+" hours ago";}},newRelativeTimeRange{UpperBound=TimeSpan.FromDays(2),MessageCreator=(delta)=>{return"yesterday";}},newRelativeTimeRange{UpperBound=DateTime.Now.Subtract(DateTime.Now.AddMonths(-1)),MessageCreator=(delta)=>{return delta.Days+" days ago";}},newRelativeTimeRange{UpperBound=DateTime.Now.Subtract(DateTime.Now.AddMonths(-2)),MessageCreator=(delta)=>{return"one month ago";}},newRelativeTimeRange{UpperBound=DateTime.Now.Subtract(DateTime.Now.AddYears(-1)),MessageCreator=(delta)=>{return(int)Math.Floor(delta.TotalDays/30)+" months ago";}},newRelativeTimeRange{UpperBound=DateTime.Now.Subtract(DateTime.Now.AddYears(-2)),MessageCreator=(delta)=>{return"one year ago";}},newRelativeTimeRange{UpperBound=TimeSpan.MaxValue,MessageCreator=(delta)=>{return(int)Math.Floor(delta.TotalDays/365.24D)+" years ago";}}};
timeRanges.Sort();}publicstaticstringGetRelativeTimeMessage(TimeSpan ago){RelativeTimeRange postRelativeDateRange = timeRanges[0];foreach(var timeRange in timeRanges){if(ago.CompareTo(timeRange.UpperBound)<=0){
postRelativeDateRange = timeRange;}}return postRelativeDateRange.MessageCreator(ago);}}
StriplingWarrior: Kemudahan membaca dan memodifikasi dibandingkan dengan pernyataan switch atau tumpukan pernyataan if / else. Kamus menjadi statis berarti bahwa itu dan objek Func <,> tidak harus dibuat setiap kali kita ingin menggunakan ToRelativeDate; itu dibuat hanya sekali, dibandingkan dengan yang saya tautkan dalam jawaban saya.
Chris Charabaruk
Saya melihat. Saya hanya berpikir, karena dokumentasi tentang Dictionarymenyatakan bahwa "Urutan pengembalian barang tidak ditentukan," ( msdn.microsoft.com/en-us/library/xfhwa508.aspx ) mungkin itu bukan struktur data terbaik untuk digunakan ketika Anda tidak peduli tentang waktu pencarian sebanyak memiliki hal-hal yang tetap tertib.
StriplingWarrior
StriplingWarrior: Saya percaya LINQ memperhitungkannya saat digunakan dengan Dictionarys. Jika Anda masih tidak nyaman dengan itu, Anda dapat menggunakannya SortedDictionary, tetapi pengalaman saya sendiri menunjukkan bahwa itu tidak perlu.
Chris Charabaruk
12
Saat Anda mengetahui zona waktu pemirsa, mungkin lebih jelas untuk menggunakan hari kalender pada skala hari. Saya tidak terbiasa dengan perpustakaan .NET jadi saya tidak tahu bagaimana Anda akan melakukannya di C #, sayangnya.
Di situs-situs konsumen, Anda juga bisa menjadi lebih mudah dalam satu menit. "Kurang dari satu menit yang lalu" atau "barusan" cukup baik.
Pertanyaannya adalah tag C # . Kenapa kode Java ini ? IMHO, hanya berlaku kode C #
Kiquenet
9
@ Jeff
var ts =newTimeSpan(DateTime.UtcNow.Ticks- dt.Ticks);
Lagi pula, lakukan pengurangan pada DateTimepengembalian TimeSpan.
Jadi Anda bisa melakukannya
(DateTime.UtcNow- dt).TotalSeconds
Saya juga terkejut melihat konstanta dikalikan dengan tangan dan kemudian komentar ditambahkan dengan perkalian masuk. Apakah itu beberapa optimasi yang salah arah?
Inilah algoritma yang digunakan stackoverflow tetapi ditulis ulang dengan lebih ringkas dalam pseudocode perlish dengan perbaikan bug (tidak ada "satu jam yang lalu"). Fungsi ini mengambil (positif) beberapa detik yang lalu dan mengembalikan string ramah-manusia seperti "3 jam yang lalu" atau "kemarin".
Anda dapat menggunakan ekstensi TimeAgo yang terlihat seperti berikut:
publicstaticstringTimeAgo(thisDateTime dateTime){string result =string.Empty;var timeSpan =DateTime.Now.Subtract(dateTime);if(timeSpan <=TimeSpan.FromSeconds(60)){
result =string.Format("{0} seconds ago", timeSpan.Seconds);}elseif(timeSpan <=TimeSpan.FromMinutes(60)){
result = timeSpan.Minutes>1?String.Format("about {0} minutes ago", timeSpan.Minutes):"about a minute ago";}elseif(timeSpan <=TimeSpan.FromHours(24)){
result = timeSpan.Hours>1?String.Format("about {0} hours ago", timeSpan.Hours):"about an hour ago";}elseif(timeSpan <=TimeSpan.FromDays(30)){
result = timeSpan.Days>1?String.Format("about {0} days ago", timeSpan.Days):"yesterday";}elseif(timeSpan <=TimeSpan.FromDays(365)){
result = timeSpan.Days>30?String.Format("about {0} months ago", timeSpan.Days/30):"about a month ago";}else{
result = timeSpan.Days>365?String.Format("about {0} years ago", timeSpan.Days/365):"about a year ago";}return result;}
Atau gunakan plugin jQuery dengan ekstensi Razor dari Timeago.
Anda dapat mengurangi beban sisi server dengan melakukan logika sisi klien ini. Lihat sumber pada beberapa halaman Digg untuk referensi. Mereka memiliki server memancarkan nilai waktu yang diproses oleh Javascript. Dengan cara ini Anda tidak perlu mengelola zona waktu pengguna akhir. Kode sisi server baru akan seperti:
Ini, saya dapatkan dari salah satu blog Bill Gates. Saya perlu menemukannya di riwayat browser saya dan saya akan memberikan Anda tautannya.
Kode Javascript untuk melakukan hal yang sama (seperti yang diminta):
function posted(t){var now =newDate();var diff = parseInt((now.getTime()-Date.parse(t))/1000);if(diff <60){return'less than a minute ago';}elseif(diff <120){return'about a minute ago';}elseif(diff <(2700)){return(parseInt(diff /60)).toString()+' minutes ago';}elseif(diff <(5400)){return'about an hour ago';}elseif(diff <(86400)){return'about '+(parseInt(diff /3600)).toString()+' hours ago';}elseif(diff <(172800)){return'1 day ago';}else{return(parseInt(diff /86400)).toString()+' days ago';}}
Pada dasarnya, Anda bekerja dalam hitungan detik ...
Saya pikir sudah ada sejumlah jawaban yang terkait dengan posting ini, tetapi orang dapat menggunakan ini yang mudah digunakan seperti plugin dan juga mudah dibaca oleh programmer. Kirim tanggal spesifik Anda, dan dapatkan nilainya dalam bentuk string:
Saya akan memberikan beberapa metode ekstensi yang berguna untuk ini dan membuat kode lebih mudah dibaca. Pertama, beberapa metode ekstensi untuk Int32.
Jawaban:
Jeff, kode Anda bagus tetapi bisa lebih jelas dengan konstanta (seperti yang disarankan dalam Kode Lengkap).
sumber
Thread.Sleep(1 * MINUTE)
? Karena itu salah dengan faktor 1000.const int SECOND = 1;
Jadi aneh satu detik adalah satu detik.plugin jquery.timeago
Jeff, karena Stack Overflow menggunakan jQuery secara ekstensif, saya merekomendasikan plugin jquery.timeago .
Manfaat:
Cukup lampirkan ke stempel waktu di DOM ready:
Ini akan mengubah semua
abbr
elemen dengan kelas timeago dan cap waktu ISO 8601 pada judul:menjadi sesuatu seperti ini:
yang menghasilkan: 4 bulan lalu. Seiring waktu berlalu, cap waktu akan secara otomatis diperbarui.
Penafian: Saya menulis plugin ini, jadi saya bias.
sumber
Begini cara saya melakukannya
Saran? Komentar? Cara meningkatkan algoritme ini?
sumber
Saya lebih suka versi ini karena keringkasannya, dan kemampuan untuk menambahkan titik centang baru. Ini bisa dienkapsulasi dengan
Latest()
ekstensi ke Timespan alih-alih 1 liner yang panjang itu, tetapi demi singkatnya dalam posting, ini bisa dilakukan. Ini memperbaiki satu jam yang lalu, 1 jam yang lalu, dengan menyediakan satu jam sampai 2 jam telah berlalusumber
SortedDictionary
alih - alih polosDictionary
: Penggunaannya sama, tetapi memastikan bahwa kunci diurutkan. Tetapi meskipun demikian, algoritmanya memiliki kekurangan, karenaRelativeDate(DateTime.Now.AddMonths(-3).AddDays(-3))
mengembalikan "95 bulan yang lalu" , terlepas dari jenis kamus yang Anda gunakan, yang tidak benar (harus mengembalikan "3 bulan lalu" atau "4 bulan lalu" tergantung pada ambang mana Anda kembali menggunakan) - bahkan jika -3 tidak membuat tanggal dalam satu tahun terakhir (saya telah menguji ini pada bulan Desember, jadi dalam kasus ini seharusnya tidak terjadi).Berikut penulisan ulang dari Jeffs Script untuk PHP:
sumber
http://refactormycode.com/codes/493-twitter-esque-relative-dates
Versi C # 6:
sumber
Func<string>
menjadiFunc<double>
.Berikut ini adalah implementasi yang saya tambahkan sebagai metode ekstensi ke kelas DateTime yang menangani tanggal di masa depan dan masa lalu dan menyediakan opsi perkiraan yang memungkinkan Anda menentukan tingkat detail yang Anda cari ("3 jam yang lalu" vs "3 jam, 23 menit, 12 detik yang lalu "):
sumber
Saya akan merekomendasikan menghitung ini di sisi klien juga. Lebih sedikit pekerjaan untuk server.
Berikut ini adalah versi yang saya gunakan (dari Zach Leatherman)
sumber
Ada juga paket yang disebut Humanizr di Nuget, dan itu benar-benar berfungsi dengan baik, dan ada di .NET Foundation.
Scott Hanselman memiliki tulisan di blognya
sumber
@ Jeff
IMHO Anda tampaknya agak panjang. Namun tampaknya sedikit lebih kuat dengan dukungan untuk "kemarin" dan "tahun". Tetapi dalam pengalaman saya ketika ini digunakan orang tersebut kemungkinan besar akan melihat konten dalam 30 hari pertama. Hanya orang-orang yang benar-benar hardcore yang datang setelah itu. Jadi itu sebabnya saya biasanya memilih untuk menjaga ini pendek dan sederhana.
Ini adalah metode yang saya gunakan saat ini di salah satu situs web saya. Ini hanya mengembalikan hari, jam, waktu relatif. Dan kemudian pengguna harus menampar "lalu" di output.
sumber
Beberapa tahun terlambat ke pesta, tetapi saya memiliki persyaratan untuk melakukan ini untuk tanggal masa lalu dan masa depan, jadi saya menggabungkan Jeff dan Vincent ke dalam ini. Ini ekstravaganza ternarytastic! :)
sumber
Apakah ada cara mudah untuk melakukan ini di Jawa? The
java.util.Date
kelas tampaknya agak terbatas.Inilah solusi Java cepat dan kotor saya:
sumber
Versi iPhone Objective-C
sumber
Mengingat dunia dan suaminya tampak memposting contoh kode, inilah yang saya tulis beberapa waktu lalu, berdasarkan pada beberapa jawaban ini.
Saya memiliki kebutuhan khusus agar kode ini dapat dilokalisasi. Jadi saya punya dua kelas -
Grammar
, yang menentukan istilah yang dapat di-lokalisasi, danFuzzyDateExtensions
, yang memiliki banyak metode ekstensi. Saya tidak perlu berurusan dengan datetimes masa depan, jadi tidak ada upaya yang dilakukan untuk menangani mereka dengan kode ini.Saya telah meninggalkan beberapa XMLdoc di sumbernya, tetapi menghapus sebagian besar (di mana mereka akan jelas) demi singkatnya. Saya juga tidak menyertakan setiap anggota kelas di sini:
The
FuzzyDateString
kelas berisi:Salah satu hal kunci yang saya ingin mencapai, serta lokalisasi, adalah bahwa "hari ini" hanya akan berarti "hari kalender ini", sehingga
IsToday
,IsThisMonth
,IsThisYear
metode terlihat seperti ini:dan metode pembulatannya seperti ini (saya sudah sertakan
RoundedMonths
, karena itu agak berbeda):Saya harap orang-orang menemukan ini berguna dan / atau menarik: o)
sumber
Dalam PHP, saya melakukannya dengan cara ini:
sumber
menggunakan Fluent DateTime
sumber
Saya pikir saya akan mencoba ini menggunakan kelas dan polimorfisme. Saya memiliki iterasi sebelumnya yang menggunakan sub-klasifikasi yang akhirnya memiliki terlalu banyak overhead. Saya telah beralih ke model objek properti delegasi / publik yang lebih fleksibel yang jauh lebih baik. Kode saya sedikit lebih akurat, saya berharap saya bisa menemukan cara yang lebih baik untuk menghasilkan "bulan lalu" yang sepertinya tidak terlalu direkayasa.
Saya pikir saya masih akan tetap dengan kasing Jeff jika-maka karena lebih sedikit kode dan lebih sederhana (itu pasti lebih mudah untuk memastikan itu akan berfungsi seperti yang diharapkan).
Untuk kode di bawah ini PrintRelativeTime.GetRelativeTimeMessage (TimeSpan lalu) mengembalikan pesan waktu relatif (misalnya "kemarin").
sumber
Sama seperti jawaban lain untuk pertanyaan ini tetapi sebagai metode ekstensi dengan kamus statis.
sumber
Dictionary
menyatakan bahwa "Urutan pengembalian barang tidak ditentukan," ( msdn.microsoft.com/en-us/library/xfhwa508.aspx ) mungkin itu bukan struktur data terbaik untuk digunakan ketika Anda tidak peduli tentang waktu pencarian sebanyak memiliki hal-hal yang tetap tertib.Dictionary
s. Jika Anda masih tidak nyaman dengan itu, Anda dapat menggunakannyaSortedDictionary
, tetapi pengalaman saya sendiri menunjukkan bahwa itu tidak perlu.Saat Anda mengetahui zona waktu pemirsa, mungkin lebih jelas untuk menggunakan hari kalender pada skala hari. Saya tidak terbiasa dengan perpustakaan .NET jadi saya tidak tahu bagaimana Anda akan melakukannya di C #, sayangnya.
Di situs-situs konsumen, Anda juga bisa menjadi lebih mudah dalam satu menit. "Kurang dari satu menit yang lalu" atau "barusan" cukup baik.
sumber
Anda dapat mencoba ini. Saya pikir itu akan berfungsi dengan benar.
sumber
Java untuk penggunaan gwt sisi klien:
sumber
@ Jeff
Lagi pula, lakukan pengurangan pada
DateTime
pengembalianTimeSpan
.Jadi Anda bisa melakukannya
Saya juga terkejut melihat konstanta dikalikan dengan tangan dan kemudian komentar ditambahkan dengan perkalian masuk. Apakah itu beberapa optimasi yang salah arah?
sumber
Inilah algoritma yang digunakan stackoverflow tetapi ditulis ulang dengan lebih ringkas dalam pseudocode perlish dengan perbaikan bug (tidak ada "satu jam yang lalu"). Fungsi ini mengambil (positif) beberapa detik yang lalu dan mengembalikan string ramah-manusia seperti "3 jam yang lalu" atau "kemarin".
sumber
Anda dapat menggunakan ekstensi TimeAgo yang terlihat seperti berikut:
Atau gunakan plugin jQuery dengan ekstensi Razor dari Timeago.
sumber
Anda dapat mengurangi beban sisi server dengan melakukan logika sisi klien ini. Lihat sumber pada beberapa halaman Digg untuk referensi. Mereka memiliki server memancarkan nilai waktu yang diproses oleh Javascript. Dengan cara ini Anda tidak perlu mengelola zona waktu pengguna akhir. Kode sisi server baru akan seperti:
Anda bahkan dapat menambahkan blok NOSCRIPT di sana dan hanya menjalankan ToString ().
sumber
Ini, saya dapatkan dari salah satu blog Bill Gates. Saya perlu menemukannya di riwayat browser saya dan saya akan memberikan Anda tautannya.
Kode Javascript untuk melakukan hal yang sama (seperti yang diminta):
Pada dasarnya, Anda bekerja dalam hitungan detik ...
sumber
Saya pikir sudah ada sejumlah jawaban yang terkait dengan posting ini, tetapi orang dapat menggunakan ini yang mudah digunakan seperti plugin dan juga mudah dibaca oleh programmer. Kirim tanggal spesifik Anda, dan dapatkan nilainya dalam bentuk string:
sumber
sumber
Jika Anda ingin memiliki keluaran seperti
"2 days, 4 hours and 12 minutes ago"
, Anda memerlukan rentang waktu:Kemudian Anda dapat mengakses nilai yang Anda sukai:
dll ...
sumber
Saya akan memberikan beberapa metode ekstensi yang berguna untuk ini dan membuat kode lebih mudah dibaca. Pertama, beberapa metode ekstensi untuk
Int32
.Lalu, satu untuk
DateTime
.Sekarang, Anda dapat melakukan sesuatu seperti di bawah ini:
sumber