【问题标题】:Get years, months, days for an elapsed span of time (DateTime)获取经过时间跨度的年、月、日 (DateTime)
【发布时间】:2018-05-28 07:19:15
【问题描述】:

如何根据日期时间选择器值将年龄显示为年、月、日。例如:

Datetimepicker value = #1/11/2014#
Today = #1/12/2015#.  

最终结果将是“1 Year, 0 Months, 1Day(S)”。但是得到这个结果不仅仅是减去DateTime.Year 值等等。有人知道数学公式或数学计算吗?

【问题讨论】:

  • 同样的问题here
  • 问之前你在谷歌上输入了什么?

标签: .net vb.net date date-difference


【解决方案1】:

这是一个 DateTimeSpan 类型,它返回一个类似于 TimeSpan 的对象,表示两个日期之间经过的年、月、日。它循环遍历时间单位以增加它们,直到较小的日期与较大的日期匹配。然后在新的DateTimeSpan 对象中返回结果增量。

Public Structure DateTimeSpan

    Private _Years As Integer
    Public ReadOnly Property Years As Integer
        Get
            Return _Years
        End Get
    End Property

    Private _Months As Integer
    Public ReadOnly Property Months As Integer
        Get
            Return _Months
        End Get
    End Property

    Private _Days As Integer
    Public ReadOnly Property Days As Integer
        Get
            Return _Days
        End Get
    End Property

    Private _Hours As Integer
    Public ReadOnly Property Hours As Integer
        Get
            Return _Hours
        End Get
    End Property

    Private _Minutes As Integer
    Public ReadOnly Property Minutes As Integer
        Get
            Return _Minutes
        End Get
    End Property

    Private _Seconds As Integer
    Public ReadOnly Property Seconds As Integer
        Get
            Return _Seconds
        End Get
    End Property

    Private _MilliSeconds As Integer
    Public ReadOnly Property MilliSeconds As Integer
        Get
            Return _MilliSeconds
        End Get
    End Property

    ' the ctor for the result
    Private Sub New(y As Integer, mm As Integer, d As Integer,
                    h As Integer, m As Integer, s As Integer,
                    ms As Integer)
        _Years = y
        _Months = mm
        _Days = d
        _Hours = h
        _Minutes = m
        _Seconds = Seconds
        _MilliSeconds = ms
    End Sub

    ' private time unit tracker when counting
    Private Enum Unit
        Year
        Month
        Day
        Complete
    End Enum

    Public Shared Function DateSpan(dt1 As DateTime, 
                                    dt2 As DateTime) As DateTimeSpan
        ' we dont do negatives
        If dt2 < dt1 Then
            Dim tmp = dt1
            dt1 = dt2
            dt2 = tmp
        End If

        Dim thisDT As DateTime = dt1
        Dim years As Integer = 0
        Dim months As Integer = 0
        Dim days As Integer = 0

        Dim level As Unit = Unit.Year
        Dim span As New DateTimeSpan()

        While level <> Unit.Complete
            Select Case level
                ' add a year until it is larger;
                ' then change the "level" to month
                Case Unit.Year
                    If thisDT.AddYears(years + 1) > dt2 Then
                        level = Unit.Month
                        thisDT = thisDT.AddYears(years)
                    Else
                        years += 1
                    End If

                Case Unit.Month
                    If thisDT.AddMonths(months + 1) > dt2 Then
                        level = Unit.Day
                        thisDT = thisDT.AddMonths(months)
                    Else
                        months += 1
                    End If

                Case Unit.Day
                    If thisDT.AddDays(days + 1) > dt2 Then
                        thisDT = thisDT.AddDays(days)
                        Dim thisTS = dt2 - thisDT
                        ' create a new DTS from the values caluclated
                        span = New DateTimeSpan(years, months, days, thisTS.Hours,
                                                thisTS.Minutes, thisTS.Seconds,
                                    thisTS.Milliseconds)
                        level = Unit.Complete
                    Else
                        days += 1
                    End If
            End Select
        End While

        Return span

    End Function

End Structure

用法:

Dim dts As DateTimeSpan = DateTimeSpan.DateSpan(#2/11/2010#, #10/21/2013#)
Console.WriteLine("{0} Yrs, {1} Months and {2} Days",
                           dts.Years.ToString, dts.Months.ToString, dts.Days.ToString)

这将给出相同的结果:

Dim dtStart As DateTime = #2/11/2010#
Dim dtEnd As new DateTime(2013, 10, 21)
' this is NOT a date and wont work:
Dim myDt = "2/11/2010"             ' its a string!

Dim dts As DateTimeSpan = DateTimeSpan.DateSpan(dtEnd, dtStart)

结果:3 Yrs, 8 Months and 10 Days

注意事项:
- 它仅适用于正确的DateTime 类型,不适用于看起来像日期的字符串。使用文字 (#...#) 或 DateTime 变量。使用DateTimePicker 时,请使用.Value 而不是.Text
- 它不做负值,所以传递的值的顺序无关紧要
- 在计算时,它会增加一个DateTime 变量,因此,它应该正确考虑闰日

这是基于我很久以前在博客中找到的一些 C# 代码(或者甚至可能来自 SO 答案或问题)。刚才找不到引用原文。

【讨论】:

    【解决方案2】:

    此方法使用循环来向后工作,但我相信这是唯一准确的方法,并且始终获得正确的值。这是因为它比您想象的要复杂 - 您需要针对闰年等进行调整。

    ''' <summary>
    ''' Finds the Years Months and Days Span between two dates
    ''' </summary>
    ''' <param name="fromDate"></param>
    ''' <param name="toDate"></param>
    ''' <returns>A String formatted as i Years j Months k Days</returns>
    ''' <remarks></remarks>
    Public Shared Function GetDateSpanText(ByVal fromDate As DateTime, Optional toDate As DateTime = Nothing) As String
            Dim years As Integer = 0, months As Integer = 0, days As Integer = 0
            If toDate = Nothing Then toDate = DateTime.Now
    
            Do Until toDate.AddYears(-1) < fromDate
                years += 1
                toDate = toDate.AddYears(-1)
            Loop
    
            Do Until toDate.AddMonths(-1) < fromDate
                months += 1
                toDate = toDate.AddMonths(-1)
            Loop
    
            Do Until toDate.AddDays(-1) < fromDate
                days += 1
                toDate = toDate.AddDays(-1)
            Loop
    
            Return String.Format("{0} Year(s) {1} Month(s) {2} Day(s)", years, months, days)
    End Function
    

    用法:

    Debug.WriteLine(GetDateSpanText(#1/11/2014#))
    

    打印:

    1 Year(s) 0 Month(s) 1 Day(s)
    

    【讨论】:

      【解决方案3】:

      此方法非常简单明了。
      不需要创建循环和类属性。

      这适用于真正的Date 类型和Strings 日期:

         'Date Picker Value
          Dim dBirthDate As Date = "#01/11/2014#"
      
          'Today
          Dim dToday As Date = "#01/12/2015#"
      
          Dim dBirthDay As Date
      
          Dim sYears As String
          Dim sDays As String
          Dim sMonths As String
          Dim sResults As String
      
      
          sYears = DateDiff(DateInterval.Year, dBirthDate, dToday)
      
          dBirthDay = dBirthDate.AddYears(sYears)
      
          sMonths = DateDiff(DateInterval.Month, dBirthDay, dToday)
      
          sDays = DateDiff(DateInterval.Day, dBirthDay, dToday)
      
      
          sResults = sYears & " Year " & sMonths & " Months " & sDays & " Day(s)"
      

      示例结果:1 年 0 个月 1 天

      【讨论】:

        【解决方案4】:

        您必须添加它才能获得完整的结果: sDays = (DateDiff(DateInterval.Day, dBirthDay, dToday)) - sMonths * 30

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-17
          • 1970-01-01
          • 2021-08-01
          • 2013-07-26
          • 1970-01-01
          • 1970-01-01
          • 2019-11-29
          • 1970-01-01
          相关资源
          最近更新 更多