"1 Ay" tanımı, hangi ay olduğuna göre değiştiğinden ve diğer cevapların hiçbiri bunu hesaba katmadığı için, bunu yapmanın en doğru yolu aslında aşağıdadır! Çerçeveye dahil edilmeyen konu hakkında daha fazla bilgi istiyorsanız, şu yazıyı okuyabilirsiniz: .Years & .Months ile Gerçek Zaman Aralığı Nesnesi (ancak, aşağıdaki işlevi anlamak ve kullanmak için bu yazıyı okumak gerekli değildir, diğerlerinin kullanmayı sevdiği yaklaşımın doğasında var olan yanlışlıklar olmadan% 100 çalışır - ve .ReverseIt işlevini yerleşik .Reverse işleviyle değiştirmekten çekinmeyin (tamlık için burada).
Lütfen, yıllara kadar herhangi bir yerde tarih / saat doğruluğu, saniye ve dakika veya saniye, dakika ve gün (6 parça / segment içerir) alabileceğinizi unutmayın. İlk ikiyi belirtirseniz ve bir yıldan eskiyse, "1 yıl ve 3 ay önce" döndürür ve geri kalanını iki segment talep ettiğiniz için iade etmez. yalnızca birkaç saatlikse, yalnızca "2 saat ve 1 dakika önce" döndürülür. Tabii ki, 1, 2, 3, 4, 5 veya 6 segment belirtirseniz aynı kurallar geçerlidir (6'da maksimuma çıkar çünkü saniye, dakika, saat, gün, ay, yıl sadece 6 tür yapar). Ayrıca 1 dakika veya daha fazla olmasına bağlı olarak "dakika" ve "dakika" gibi gramer sorunlarını düzeltir, tüm türler için aynıdır ve oluşturulan "dize" her zaman dilbilgisi açısından doğru olacaktır.
İşte kullanım için bazı örnekler: bAllowSegments, kaç segmentin gösterileceğini tanımlar ... yani: 3 ise, dönüş dizesi (örnek olarak) "3 years, 2 months and 13 days"
olacaktır ... (ilk 3 kez saat, dakika ve saniye içermez kategoriler döndürülür), ancak tarih birkaç gün önceki gibi daha yeni bir tarihse, "4 days, 1 hour and 13 minutes ago"
bunun yerine aynı segmentleri (3) belirtmek geri dönecektir , bu nedenle her şeyi hesaba katar!
bAllowSegments 2 ise, geri döner "3 years and 2 months"
ve 6 (maksimum değer) dönerse "3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
, ancak ilk 3 segmentte tarih verisi olmadığını anladığı ve 6 segment belirleseniz bile bunları yok saydığı için bunun NEVER RETURN
gibi bir şey olacağı hatırlatılır. "0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
, bu yüzden endişelenme :). Elbette, içinde 0 olan bir segment varsa, dizeyi oluştururken bunu dikkate alacak "3 days and 4 seconds ago"
ve "0 saat" kısmı olarak ve yok sayarak gösterecektir ! Keyfini çıkarın ve isterseniz yorum yapın.
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
Elbette, bir kaynak dizeyi alan bir "ReplaceLast" işlevine ve neyin değiştirilmesi gerektiğini belirten bir bağımsız değişkene ve onu neyle değiştirmek istediğinizi belirten başka bir bağımsız değişkene ihtiyacınız olacak ve yalnızca o dizenin son geçtiği yeri değiştirecek ... eğer sahip değilseniz veya uygulamak istemiyorsanız benimkini dahil ettim, işte burada, hiçbir değişiklik gerekmeden "olduğu gibi" çalışacaktır. Tersine çevirme işlevine artık gerek olmadığını biliyorum (.net'te var), ancak ReplaceLast ve ReverseIt işlevi ön-net günlerden taşınıyor, bu yüzden lütfen nasıl eski göründüğünü özür dilerim (hala% 100 çalışıyor, kullanıyor em, on yıldan fazla bir süredir hatasız olduklarını garanti edebilirler) ... :). şerefe.
<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