아래는 실제로 가장 정확한 방법입니다. "1 개월"의 정의는 월에 따라 달라 지므로 다른 답변들도이를 고려하지 않습니다! 프레임 워크에 포함되지 않은 문제에 대한 자세한 정보가 필요하면이 게시물을 읽을 수 있습니다. .Years & .Months를 사용한 실시간 타임스 팬 오브젝트 (그러나 해당 게시물을 읽는 것이 아래 기능을 이해하고 사용할 필요는 없습니다. 그것은 다른 사람들이 사용하기를 좋아하는 근사치의 본질적인 부정확성없이 100 % 작동합니다. 그리고 .ReverseIt 함수를 기본 제공 .Reverse 함수로 자유롭게 교체하십시오 (완전히 여기에 있습니다).
최대 몇 년 (6 개 부품 / 세그먼트 포함)의 날짜 / 시간 정확도, 초 및 분 또는 초, 분 및 일 수에 관계없이 얻을 수 있습니다. 상위 2 개를 지정하고 1 년이 지난 경우 "1 년 3 개월 전"을 반환하고 두 개의 세그먼트를 요청 했으므로 나머지는 반환하지 않습니다. 몇 시간이 지난 경우 "2 시간 1 분 전"만 반환됩니다. 물론 1, 2, 3, 4, 5 또는 6 세그먼트를 지정하면 동일한 규칙이 적용됩니다 (초, 분, 시간, 일, 월, 연도는 6 가지 유형 만 만들기 때문에 6으로 최대 값을 초과 함). 또한 모든 유형에 대해 1 분 이상인지 여부에 따라 "분"대 "분"과 같은 그래머 문제를 수정하며 생성 된 "문자열"은 문법적으로 항상 정확합니다.
다음은 사용할 예제입니다. bAllowSegments는 표시 할 세그먼트 수를 식별합니다. 즉, 3 인 경우 반환 문자열은 (예를 들어) ... "3 years, 2 months and 13 days"
(상위 3 시간으로시, 분, 초는 포함하지 않음 ) 그러나 날짜가 며칠 전과 같은 최신 날짜 인 경우 동일한 세그먼트 (3)를 지정하면 "4 days, 1 hour and 13 minutes ago"
대신 반환 되므로 모든 것이 고려됩니다.
bAllowSegments이 2 인 경우는 반환 "3 years and 2 months"
및 6 (최대 값)을 반환하는 경우 "3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
는 것을 상기시켜,하지만, NEVER RETURN
이런 식으로 뭔가를 "0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
당신이 6 개 세그먼트를 지정하는 경우에도, 상위 3 개 세그먼트와 무시 그들을에는 날짜 데이터가없는 이해로 걱정하지 마십시오 :). 물론 0이 포함 된 세그먼트가 있으면 문자열을 형성 할 때이를 고려 "3 days and 4 seconds ago"
하여 "0 시간"부분으로 표시 하고 무시합니다! 당신이 좋아하면 즐기고 의견을 말하십시오.
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
물론, "ReplaceLast"함수가 필요합니다.이 함수는 소스 문자열과 대체 할 항목을 지정하는 인수 및이를 대체하려는 항목을 지정하는 인수가 필요하며 해당 문자열의 마지막 발생 만 대체합니다. ... 내가 없거나 구현하고 싶지 않은 경우 내 것을 포함 시켰으므로 여기에서는 수정없이 "있는 그대로"작동합니다. 리버스 기능이 더 이상 필요하지 않다는 것을 알고 있습니다 (.net에 존재 함). ReplaceLast 및 ReverseIt 기능은 .net 이전 일부터 이월되므로 날짜가 어떻게 생겼는지 변명하십시오 (여전히 100 % 작동, 사용 중임) 10 년 이상 동안, 버그가 없다고 보증 할 수 있습니다) : ...). 건배.
<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