Question

I'm trying to calculate the "timeago" and I'm coming up with a descrepancy in my code.

Using Today's Date

November 7, 2010

If I use September 1, 2010 then both my .NET code and my JS code say "2 months"

If I use August 31, 2010 then my .NET code says "3 months" and my JS code says at "2 months"

This discrepancy stays until August 9, 2010.

Basically the dateDiff is "off" from August 10 - August 31 based on todays date of November 7.

Here's the JavaScript (taken from "timeago" plugin)

    var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
    seconds < 90 && substitute($l.minute, 1) ||
    minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
    minutes < 90 && substitute($l.hour, 1) ||
    hours < 24 && substitute($l.hours, Math.round(hours)) ||
    hours < 48 && substitute($l.day, 1) ||
    days < 30 && substitute($l.days, Math.floor(days)) ||
    days < 60 && substitute($l.month, 1) ||
    days < 365 && substitute($l.months, Math.floor(days / 30)) ||
    years < 2 && substitute($l.year, 1) ||
    substitute($l.years, Math.floor(years));

And here's my .NET code (written by me)

    Public Function ToDuration(ByVal dt As Date?, _
                               Optional ByVal suffixAgo As String = Nothing) As String

        If Not dt Is Nothing Then
            Dim theDate As Date = dt
            Dim SecondsAppart As Integer = DateDiff(DateInterval.Second, theDate, Now)
            Dim output As String
            If SecondsAppart < 86400 Then
                Select Case SecondsAppart
                    Case Is <= 59 : output = "less than a minute " & suffixAgo
                    Case Is <= 119 : output = "about a minute " & suffixAgo
                    Case Is <= 3599 : output = DateDiff(DateInterval.Minute, theDate, Now) & " minutes " & suffixAgo
                    Case Is <= 7199 : output = "about an hour " & suffixAgo
                    Case Else : output = DateDiff(DateInterval.Hour, theDate, Now) & " hours " & suffixAgo
                End Select

            Else
                Dim DaysAppart As Integer = DateDiff(DateInterval.Day, theDate, Now)
                Select Case DaysAppart
                    Case Is <= 1 : output = "yesterday"
                    Case Is <= 30 : output = DateDiff(DateInterval.Day, theDate, Now) & " days " & suffixAgo
                    Case Is <= 60 : output = "about a month " & suffixAgo
                    Case Is <= 365 : output = DateDiff(DateInterval.Month, theDate, Now) & " months " & suffixAgo
                    Case Is <= 730 : output = "about a year " & suffixAgo
                    Case Else : output = DateDiff(DateInterval.Year, theDate, Now) & " years " & suffixAgo
                End Select
            End If

            Return output
        Else
            Return String.Empty
        End If
    End Function

So the problem I'm having is a fundamental one as well as a logistic one.

  1. Which code is "right" when it comes to DateDiff? (IE: Is 2 months and 14 days considered 2 months or 3?)
  2. What is the best way to get them to line up accordingly?
Was it helpful?

Solution

Made some assumptions and had to write it in C#, but this version of the code gives me 2 months for August 31 and 3 months for August 9

        public static string ToDuration(DateTime dt, string suffixAgo)
        {
            string output;
            DateTime theDate;
            if (dt == null)
            {
                output = "now";
            }
            else
            {
                theDate = dt;
                TimeSpan DateInterval = DateTime.Now - theDate;
                int SecondsAppart = Convert.ToInt32(Math.Floor(DateInterval.TotalSeconds));
                if ((SecondsAppart < 86400))
                {

                    if (SecondsAppart < 59)
                        output = ("less than a minute " + suffixAgo);
                    else if (SecondsAppart < 119)
                        output = ("about a minute " + suffixAgo);
                    else if (SecondsAppart < 3599)
                        output = string.Format("{0} minutes {1}", Math.Floor(DateInterval.TotalMinutes), suffixAgo);
                    else if (SecondsAppart < 7199)
                        output = "about an hour " + suffixAgo;
                    else
                        output = string.Format("{0} hours {1}", Math.Floor(DateInterval.TotalHours), suffixAgo);
                }
                else
                {
                    int DaysAppart = Convert.ToInt32(DateInterval.TotalDays);
                    if (DaysAppart <= 1)
                        output = "yesterday";
                    else if (DaysAppart < 30)
                        output = string.Format("{0} days {1}", Math.Floor(DateInterval.TotalDays), suffixAgo);
                    else if (DaysAppart < 60)
                        output = "about a month " + suffixAgo;
                    else if (DaysAppart < 365)
                        output = string.Format("{0} months {1}", Math.Floor(DateInterval.TotalDays/30), suffixAgo);
                    else if (DaysAppart < 730)
                        output = ("about a year " + suffixAgo);
                    else
                        output = string.Format("{0} year {1}", Math.Floor(DateInterval.TotalDays/365), suffixAgo);
                }
            }
            return output;
        }

I've updated the code and I think you have the results you're expecting now. Hopefuly this will help.

Cheers, Wagner.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top