Несоответствие расчета даты (JavaScript VS .NET)

Я пытаюсь рассчитать «время назад», и у меня возникает несоответствие в моем коде.

Использование сегодняшней даты

7 ноября 2010 г.

Если я использую 1 сентября 2010 г., то и в коде .NET, и в коде JS указано «2 месяца».

Если я использую 31 августа 2010 г., тогда в моем коде .NET указано «3 месяца», а в коде JS — «2 месяца».

Это несоответствие сохраняется до 9 августа 2010 г..

В основном dateDiff «выключен» с 10 августа по 31 августа, исходя из сегодняшней даты 7 ноября.

Вот код JavaScript (взято из плагина timeago)

    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));

А вот мой код .NET (написанный мной)

    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

Итак, проблема, с которой я сталкиваюсь, является фундаментальной, а также логистической.

  1. Какой код является «правильным», когда речь идет о DateDiff? (IE: считать 2 месяца и 14 дней 2 месяцами или 3?)
  2. Каков наилучший способ заставить их выстроиться соответствующим образом?

person Chase Florell    schedule 08.11.2010    source источник
comment
Одна вещь, которую я бы сделал, это заменил ‹= на ‹. Судя по тому, как работает ваш код сейчас, вы говорите, что два месяца — это примерно месяц назад. То же, что 730 дней - это примерно год.   -  person Wagner Silveira    schedule 08.11.2010
comment
Интересно, случайно ли вы выбрали дату, когда часовой пояс в большей части США меняется с дневного на стандартное время?   -  person kennebec    schedule 08.11.2010
comment
ха-ха, я даже не думал о переходе на летнее время. Не уверен, применимо ли оно здесь или нет.   -  person Chase Florell    schedule 08.11.2010
comment
@Wagner - вот где вступают в действие основы. 1 день меньше месяца = 2 месяцам или 1? Помните, что 2 месяца — это почти всегда 61 день.   -  person Chase Florell    schedule 08.11.2010


Ответы (1)


Сделал некоторые предположения и пришлось писать на C#, но эта версия кода дает мне 2 месяца на 31 августа и 3 месяца на 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;
        }

Я обновил код, и я думаю, что у вас есть результаты, которые вы ожидаете сейчас. Надеюсь, это поможет.

Здоровья, Вагнер.

person Wagner Silveira    schedule 08.11.2010
comment
Я думаю, что это ближе, но если я войду 15 августа, я получу 2 месяца в JS и 3 месяца в .NET. - person Chase Florell; 08.11.2010
comment
PS: мне кажется, что string.Format мне нравится намного больше... не знаю, почему я об этом не подумал. - person Chase Florell; 08.11.2010
comment
Кажется, я понял... Если в операторах if вы замените Convert.ToInt32 на Math.Floor, вы должны получить ожидаемые результаты. Что имеет смысл, потому что это именно то, что делает код js. Я обновляю код, чтобы отразить это. - person Wagner Silveira; 08.11.2010
comment
ха-ха, я не видел вашу правку. Я только что сделал именно это и пришел сюда, чтобы опубликовать свой ответ ... похоже, вы меня опередили. Работает как чемпион!!! - person Chase Florell; 12.11.2010