Di bawah ini sebenarnya adalah cara paling akurat yang dapat Anda lakukan, karena definisi "1 Bulan" berubah tergantung pada bulan itu, dan bukan jawaban lain yang memperhitungkannya! Jika Anda ingin informasi lebih lanjut tentang masalah yang tidak ada dalam kerangka kerja, Anda dapat membaca posting ini: Objek Timespan Nyata Dengan .Years & .Months (namun, membaca posting itu tidak perlu untuk memahami dan menggunakan fungsi di bawah ini, ini bekerja 100%, tanpa ketidakakuratan bawaan dari perkiraan yang suka digunakan orang lain - dan jangan ragu untuk mengganti fungsi .ReverseIt dengan built-in. Fungsi reverse yang mungkin Anda miliki pada kerangka kerja Anda (hanya ada di sini untuk kelengkapan).
Harap dicatat bahwa Anda bisa mendapatkan sejumlah tanggal / waktu akurasi, detik & menit, atau detik, menit dan hari, di mana saja hingga bertahun-tahun (yang akan mengandung 6 bagian / segmen). Jika Anda menentukan dua teratas dan lebih dari satu tahun, itu akan mengembalikan "1 tahun dan 3 bulan yang lalu" dan tidak akan mengembalikan sisanya karena Anda telah meminta dua segmen. jika hanya beberapa jam, maka itu hanya akan mengembalikan "2 jam dan 1 menit yang lalu". Tentu saja, aturan yang sama berlaku jika Anda menentukan 1, 2, 3, 4, 5 atau 6 segmet (maksimal 6 karena detik, menit, jam, hari, bulan, tahun hanya membuat 6 jenis). Itu juga akan memperbaiki masalah grammer seperti "menit" vs "menit" tergantung pada apakah itu 1 menit atau lebih, sama untuk semua jenis, dan "string" yang dihasilkan akan selalu benar secara tata bahasa.
Berikut adalah beberapa contoh untuk digunakan: bAllowSegments mengidentifikasi berapa banyak segmen yang ditampilkan ... yaitu: jika 3, maka kembalikan string akan menjadi (sebagai contoh) ... "3 years, 2 months and 13 days"
(tidak akan memasukkan jam, menit dan detik sebagai 3 waktu teratas) kategori dikembalikan), namun jika tanggalnya adalah tanggal yang lebih baru, seperti sesuatu beberapa hari yang lalu, tentukan segmen yang sama (3) yang akan dikembalikan "4 days, 1 hour and 13 minutes ago"
sebagai gantinya, sehingga memperhitungkan semuanya!
jika bAllowSegments adalah 2 ia akan kembali "3 years and 2 months"
dan jika 6 (nilai maksimum) akan kembali "3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
, tetapi, diingatkan bahwa itu akan menjadi NEVER RETURN
sesuatu seperti ini "0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
karena memahami tidak ada data tanggal di 3 segmen teratas dan mengabaikannya, bahkan jika Anda menentukan 6 segmen , jadi jangan khawatir :). Tentu saja, jika ada segmen dengan 0 di dalamnya, itu akan memperhitungkannya saat membentuk string, dan akan ditampilkan sebagai "3 days and 4 seconds ago"
dan mengabaikan bagian "0 jam"! Nikmati dan berikan komentar jika Anda mau.
Public Function RealTimeUntilNow(ByVal dt As DateTime, Optional ByVal bAllowSegments As Byte = 2) As String
' bAllowSegments identifies how many segments to show... ie: if 3, then return string would be (as an example)...
' "3 years, 2 months and 13 days" the top 3 time categories are returned, if bAllowSegments is 2 it would return
' "3 years and 2 months" and if 6 (maximum value) would return "3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
Dim rYears, rMonths, rDays, rHours, rMinutes, rSeconds As Int16
Dim dtNow = DateTime.Now
Dim daysInBaseMonth = Date.DaysInMonth(dt.Year, dt.Month)
rYears = dtNow.Year - dt.Year
rMonths = dtNow.Month - dt.Month
If rMonths < 0 Then rMonths += 12 : rYears -= 1 ' add 1 year to months, and remove 1 year from years.
rDays = dtNow.Day - dt.Day
If rDays < 0 Then rDays += daysInBaseMonth : rMonths -= 1
rHours = dtNow.Hour - dt.Hour
If rHours < 0 Then rHours += 24 : rDays -= 1
rMinutes = dtNow.Minute - dt.Minute
If rMinutes < 0 Then rMinutes += 60 : rHours -= 1
rSeconds = dtNow.Second - dt.Second
If rSeconds < 0 Then rSeconds += 60 : rMinutes -= 1
' this is the display functionality
Dim sb As StringBuilder = New StringBuilder()
Dim iSegmentsAdded As Int16 = 0
If rYears > 0 Then sb.Append(rYears) : sb.Append(" year" & If(rYears <> 1, "s", "") & ", ") : iSegmentsAdded += 1
If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn
If rMonths > 0 Then sb.AppendFormat(rMonths) : sb.Append(" month" & If(rMonths <> 1, "s", "") & ", ") : iSegmentsAdded += 1
If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn
If rDays > 0 Then sb.Append(rDays) : sb.Append(" day" & If(rDays <> 1, "s", "") & ", ") : iSegmentsAdded += 1
If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn
If rHours > 0 Then sb.Append(rHours) : sb.Append(" hour" & If(rHours <> 1, "s", "") & ", ") : iSegmentsAdded += 1
If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn
If rMinutes > 0 Then sb.Append(rMinutes) : sb.Append(" minute" & If(rMinutes <> 1, "s", "") & ", ") : iSegmentsAdded += 1
If bAllowSegments = iSegmentsAdded Then GoTo parseAndReturn
If rSeconds > 0 Then sb.Append(rSeconds) : sb.Append(" second" & If(rSeconds <> 1, "s", "") & "") : iSegmentsAdded += 1
parseAndReturn:
' if the string is entirely empty, that means it was just posted so its less than a second ago, and an empty string getting passed will cause an error
' so we construct our own meaningful string which will still fit into the "Posted * ago " syntax...
If sb.ToString = "" Then sb.Append("less than 1 second")
Return ReplaceLast(sb.ToString.TrimEnd(" ", ",").ToString, ",", " and")
End Function
Tentu saja, Anda akan memerlukan fungsi "ReplaceLast", yang mengambil string sumber, dan argumen yang menentukan apa yang perlu diganti, dan argumen lain yang menentukan dengan apa Anda ingin menggantinya, dan itu hanya menggantikan kejadian terakhir dari string itu. ... saya telah memasukkan yang saya miliki jika Anda tidak memilikinya atau tidak ingin mengimplementasikannya, jadi ini dia, itu akan berfungsi "sebagaimana adanya" tanpa modifikasi yang diperlukan. Saya tahu fungsi reverseit tidak lagi diperlukan (ada di .net) tetapi fungsi ReplaceLast dan ReverseIt dijalankan dari hari-hari pra-.net, jadi mohon maafkan bagaimana tanggalnya kelihatannya (masih berfungsi 100% tho, telah menggunakan em selama lebih dari sepuluh tahun, dapat menjamin mereka bebas bug) ... :). Bersulang.
<Extension()> _
Public Function ReplaceLast(ByVal sReplacable As String, ByVal sReplaceWhat As String, ByVal sReplaceWith As String) As String
' let empty string arguments run, incase we dont know if we are sending and empty string or not.
sReplacable = sReplacable.ReverseIt
sReplacable = Replace(sReplacable, sReplaceWhat.ReverseIt, sReplaceWith.ReverseIt, , 1) ' only does first item on reversed version!
Return sReplacable.ReverseIt.ToString
End Function
<Extension()> _
Public Function ReverseIt(ByVal strS As String, Optional ByVal n As Integer = -1) As String
Dim strTempX As String = "", intI As Integer
If n > strS.Length Or n = -1 Then n = strS.Length
For intI = n To 1 Step -1
strTempX = strTempX + Mid(strS, intI, 1)
Next intI
ReverseIt = strTempX + Right(strS, Len(strS) - n)
End Function