Dưới đây thực sự là cách chính xác nhất mà bạn có thể thực hiện, vì định nghĩa của "1 tháng" thay đổi tùy thuộc vào tháng nào và không có câu trả lời nào khác có tính đến điều này! Nếu bạn muốn biết thêm thông tin về vấn đề không được xây dựng trong khung, bạn có thể đọc bài đăng này: Đối tượng thời gian thực với .Years & .Months (tuy nhiên, đọc bài đăng đó không cần thiết để hiểu và sử dụng chức năng bên dưới, nó hoạt động 100%, không có sự thiếu chính xác vốn có của phép tính gần đúng mà người khác thích sử dụng - và thoải mái thay thế hàm .ReverseIt bằng hàm .Reverse tích hợp mà bạn có thể có trên khung của mình (nó chỉ ở đây để hoàn thiện).
Xin lưu ý rằng bạn có thể nhận được bất kỳ số ngày / lần chính xác, giây & phút, hoặc giây, phút và ngày, bất cứ nơi nào lên đến nhiều năm (sẽ chứa 6 phần / phân đoạn). Nếu bạn chỉ định hai người đứng đầu và hơn một tuổi, nó sẽ trả về "1 năm và 3 tháng trước" và sẽ không trả lại phần còn lại vì bạn đã yêu cầu hai phân đoạn. nếu nó chỉ mới vài giờ, thì nó sẽ chỉ trở lại "2 giờ 1 phút trước". Tất nhiên, các quy tắc tương tự được áp dụng nếu bạn chỉ định 1, 2, 3, 4, 5 hoặc 6 segmets (tối đa là 6 vì giây, phút, giờ, ngày, tháng, năm chỉ tạo ra 6 loại). Nó cũng sẽ sửa các vấn đề ngữ pháp như "phút" so với "phút" tùy thuộc vào việc đó là 1 phút trở lên, giống nhau cho tất cả các loại và "chuỗi" được tạo sẽ luôn đúng về mặt ngữ pháp.
Dưới đây là một số ví dụ để sử dụng: b ALLowSegments xác định có bao nhiêu phân đoạn sẽ hiển thị ... tức là: nếu 3, thì chuỗi trả về sẽ là (ví dụ) ... "3 years, 2 months and 13 days"
(sẽ không bao gồm giờ, phút và giây là 3 thời gian hàng đầu các danh mục được trả về), tuy nhiên, ngày là một ngày mới hơn, chẳng hạn như một vài ngày trước, chỉ định các phân đoạn tương tự (3) sẽ trở lại "4 days, 1 hour and 13 minutes ago"
thay vào đó, vì vậy nó sẽ tính đến mọi thứ!
nếu b ALLowSegments là 2 thì nó sẽ trả về "3 years and 2 months"
và nếu 6 (giá trị tối đa) sẽ trả về "3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
, nhưng, xin lưu ý rằng nó sẽ NEVER RETURN
giống như thế này "0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
vì nó hiểu rằng không có dữ liệu ngày trong 3 phân đoạn hàng đầu và bỏ qua chúng, ngay cả khi bạn chỉ định 6 phân đoạn , đừng lo lắng :). Tất nhiên, nếu có một phân đoạn có 0 trong đó, nó sẽ tính đến điều đó khi tạo chuỗi và sẽ hiển thị dưới dạng "3 days and 4 seconds ago"
và bỏ qua phần "0 giờ"! Thưởng thức và xin vui lòng bình luận nếu bạn thích.
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
Tất nhiên, bạn sẽ cần một hàm "Thay thế", lấy một chuỗi nguồn và một đối số chỉ định những gì cần được thay thế và một đối số khác chỉ định những gì bạn muốn thay thế nó và nó chỉ thay thế lần xuất hiện cuối cùng của chuỗi đó ... Tôi đã bao gồm một cái của tôi nếu bạn không có hoặc không muốn thực hiện nó, vì vậy ở đây, nó sẽ hoạt động "như hiện tại" mà không cần sửa đổi. Tôi biết chức năng Reverseit không còn cần thiết nữa (tồn tại trong .net) nhưng chức năng REPLast và ReverseIt được thực hiện từ những ngày trước.net, vì vậy xin vui lòng xem ngày đó có vẻ như thế nào (vẫn hoạt động 100% tho, đang sử dụng trong hơn mười năm, có thể đảm bảo họ không có lỗi) ... :). chúc mừng
<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