Разница между датой и временем верна, нет месяцев и даже лет? - PullRequest
3 голосов
/ 29 июня 2011

Есть ли встроенная функция, как я могу получить разницу между объектами DateTime лучше, чем просто количество дней? Я имею в виду что-то вроде 1 месяца, 23 дня. Я считаю, что это довольно сложно рассчитать из-за разного количества дней в каждом месяце, високосных лет и т. Д. Спасибо

Ответы [ 8 ]

5 голосов
/ 29 июня 2011

Взгляните на Время Ноды .В целом он еще не готов к работе, но соответствующие биты могут работать достаточно хорошо для ваших текущих требований:)

Обратите внимание, что TimeSpan будет не делать то, что вы хотите, потому что "1Месяц "может означать различное количество дней в зависимости от месяца, и TimeSpan не привязан.

В Noda Time вы хотите Period.Например:

LocalDate start = new LocalDate(2010, 4, 15);
LocalDate end = new LocalDate(2010, 6, 19);
Period period = Period.Between(start, end); // Defaults to Year/Month/Day

Console.WriteLine(period.Months); // 2
Console.WriteLine(period.Days); // 4

Обратите внимание, что арифметика даты / времени является сложной ... в некоторых случаях «правильный ответ» вовсе не очевиден.

3 голосов
/ 29 июня 2011

Месяцы могут состоять из 28, 29, 30 или 31 дня;годы могут быть 365 или 366 дней.Поэтому возникают проблемы, когда вы пытаетесь рассчитать полные единицы времени для месяцев и лет, поэтому, если вы можете что-то предположить, вы можете проверить это из

3 голосов
/ 29 июня 2011

Простое вычитание сделает работу:

int months = departure.Months - arrival.Months;
int years = departure.Years - arrival.Years;
//in case multiple years have elapsed .
int months += years * 12;

Вы, очевидно, должны были бы заняться математикой, когда дело доходит до дней, если вам не нужна точность, если разница в днях отрицательна, вам нужно будет вычесть одно из числа месяца.


И тогда вы можете использовать TimeSpan Для получения большей точности, т.е. прошедшего времени.

//Microsoft Documentation Example:

DateTime departure = new DateTime(2010, 6, 12, 18, 32, 0);
DateTime arrival = new DateTime(2010, 6, 13, 22, 47, 0);
TimeSpan travelTime = arrival - departure;  
Console.WriteLine("{0} - {1} = {2}", arrival, departure, travelTime);   

// The example displays the following output:
//       6/13/2010 10:47:00 PM - 6/12/2010 6:32:00 PM = 1.04:15:00
1 голос
/ 29 июня 2011

Вот код, который я только что написал, чтобы вычислить разницу в годах, месяцах и днях. Находится в свободном доступе.

    public sealed class DateDifference {
            int years;

            public int Years {
                get { return years; }
            }
            int months;

            public int Months {
                get { return months; }
            }
            int days;

            public int Days {
                get { return days; }
            }

            public override string ToString()
            {
                return string.Format("[DateDifference Years={0}, Months={1}, Days={2}]", years, months, days);
            }


            public DateDifference(DateTime earlier, DateTime later){
                if(later<earlier)
                    throw new ArgumentException("later is earlier than 'earlier'.");
                bool isleapday=(earlier.Month==2 && earlier.Day==29);
                DateTime tmp=isleapday ? new DateTime(earlier.Year,2,28) : earlier;
                while(true){
                    try {
                        tmp=tmp.AddYears(1);
                        if(isleapday && DateTime.IsLeapYear(tmp.Year))
                            tmp=new DateTime(tmp.Year,2,29);
                    } catch(ArgumentOutOfRangeException){
                        break;
                    }
                    if(tmp<=later){
                        years++;
                        earlier=tmp;
                    } else {
                        break;
                    }
                }
                // Add months
                tmp=earlier;
                while(true){
                    try {
                        tmp=tmp.AddMonths(1);
                    if(isleapday && tmp.Day!=29 && tmp.Month!=2)
                        tmp=new DateTime(tmp.Year,tmp.Month,29);
                    } catch(ArgumentOutOfRangeException){
                        break;
                    }
                    if(tmp<=later){
                        months++;
                        earlier=tmp;
                    } else {
                        break;
                    }
                }
                tmp=earlier;
                while(true){
                    try {
                        tmp=tmp.AddDays(1);
                    } catch(ArgumentOutOfRangeException){
                        break;
                    }
                    if(tmp<=later){
                        days++;
                        earlier=tmp;
                    } else {
                        break;
                    }
                }
            }
        }

Пример:

var dd=new DateDifference(new DateTime(2010,6,29),new DateTime(2012,2,29));
Console.WriteLine(dd.Years); // displays 1
Console.WriteLine(dd.Months); // displays 8
Console.WriteLine(dd.Days); // displays 0
1 голос
/ 29 июня 2011

Этот тип проблемы на удивление трудно определить для календарных дат.Посмотрите здесь для хорошего расчета того, как рассчитать возраст человека в годах.

Рассчитать возраст в C #

Сложность исходит из крайних случаев.Очевидно, 31 января - месяц после 31 декабря.Но 28 февраля - это месяц после 31 января?В нормальный год?В високосный год?Прежде чем вы сможете закодировать это, вам нужно указать такие случаи.

Алгоритм дня рождения использует стратегию округления и уменьшения.Это сработает и для разницы за месяц, учитывая ваш ответ на вопрос в предыдущем абзаце.

0 голосов
/ 31 марта 2014

Вот класс, который позволяет вам запрашивать различные свойства разности пары DateTimes. Я просто взбил его сейчас и публикую в открытом доступе. Делайте это как хотите, но используйте на свой страх и риск.

public static class DateCalcs
{
    /// <summary>
    /// returns the integer number of years between start and finish
    /// </summary>
    /// <param name="start">Start DateTime</param>
    /// <param name="finish">FinishDateTime</param>
    /// <returns></returns>
    public static int YearDiff(DateTime start, DateTime finish)
    {
        DateTime _start, _finish;
        bool _negate = (finish < start);
        if(_negate)
        {
            _start = finish;
            _finish = start;
        }
        else
        {
            _start = start;
            _finish = finish;
        }
        int _diff = 0;
        while(_start.AddYears(1) < _finish)
        {
            _diff++;
            _start = _start.AddYears(1);
        }

        if(_negate)
        {
            _diff = _diff * (-1);
        }

        return _diff;
    }

    /// <summary>
    /// returns the integer number of months between start and finish
    /// </summary>
    /// <param name="start">Start DateTime</param>
    /// <param name="finish">Finish DateTime</param>
    /// <returns></returns>
    public static int MonthDiff(DateTime start, DateTime finish)
    {
        DateTime _start, _finish;
        bool _negate = (finish < start);
        if (_negate)
        {
            _start = finish;
            _finish = start;
        }
        else
        {
            _start = start;
            _finish = finish;
        }
        int _diff = 0;
        while (_start.AddMonths(1) < _finish)
        {
            _diff++;
            _start = _start.AddMonths(1);
        }

        if (_negate)
        {
            _diff = _diff * (-1);
        }

        return _diff;
    }

    /// <summary>
    /// returns the integer number of days between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int DayDiff(DateTime start, DateTime finish)
    {

        var _diff = finish - start;
        return (int)_diff.TotalDays;
    }

    /// <summary>
    /// returns the integer number of hours between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int HourDiff(DateTime start, DateTime finish)
    {
        var _diff = finish - start;
        return(int)_diff.TotalHours;
    }

    /// <summary>
    /// returns the integer number of minutes between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int MinuteDiff(DateTime start, DateTime finish)
    {
        var _diff = finish - start;
        return (int)_diff.TotalMinutes;
    }

    /// <summary>
    /// returns the integer number of seconds between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int SecondDiff(DateTime start, DateTime finish)
    {
        var _diff = finish - start;
        return (int)_diff.TotalSeconds;
    }

    /// <summary>
    /// returns the integer number of milliseconds between start and finish
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int MilliSecondDiff(DateTime start, DateTime finish)
    {
        var _diff = finish - start;
        return (int)_diff.TotalMilliseconds;
    }

    /// <summary>
    /// returns the integer remaining number of months between two DateTimes 
    /// after the year difference has been removed
    /// </summary>
    /// <param name="start">start DateTime</param>
    /// <param name="finish">finish DateTime</param>
    /// <returns></returns>
    public static int MonthPartDiff(DateTime start, DateTime finish)
    {
        return MonthDiff(start.AddYears(YearDiff(start, finish)), finish);
    }

    /// <summary>
    /// returns the integer remaining number of days between two DateTimes 
    /// after the year difference and the month difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int DayPartDiff(DateTime start, DateTime finish)
    {
        return DayDiff(start.AddMonths(MonthDiff(start, finish)), finish);
    }

    /// <summary>
    /// returns the integer remaining number of hours between two DateTimes 
    /// after the year, month and day difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int HourPartDiff(DateTime start, DateTime finish)
    {
        return (finish-start).Hours;
    }

    /// <summary>
    /// returns the integer remaining number of minutes between two DateTimes 
    /// after the year, month, day and hour difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int MinutePartDiff(DateTime start, DateTime finish)
    {
        return (finish-start).Minutes;
    }

    /// <summary>
    /// returns the integer remaining number of seconds between two DateTimes 
    /// after the year, month, day, hour and minute difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int SecondPartDiff(DateTime start, DateTime finish)
    {
        return (finish - start).Seconds;
    }

    /// <summary>
    /// returns the integer remaining number of milliseconds between two DateTimes 
    /// after the year, month, day, hour, minute and second difference has been removed
    /// </summary>
    /// <param name="start"></param>
    /// <param name="finish"></param>
    /// <returns></returns>
    public static int MilliSecondPartDiff(DateTime start, DateTime finish)
    {
        return (finish - start).Milliseconds;
    }

}

Так что вы можете назвать это так:

var finish = DateTime.Now;
var start = new DateTime(1967, 7, 3);

var years = DateCalcs.YearDiff(start, finish);
Console.WriteLine ("Age in years: {0}", years);
var months = DateCalcs.MonthDiff(start, finish);
Console.WriteLine("Age in months: {0}", months);
var days = DateCalcs.DayDiff(start, finish);
Console.WriteLine("Age in days: {0}", days);
var hours = DateCalcs.HourDiff(start, finish);
Console.WriteLine("Age in hours: {0}", hours);
var minutes = DateCalcs.MinuteDiff(start, finish);
Console.WriteLine("Age in minutes: {0}", minutes);
var seconds = DateCalcs.SecondDiff(start, finish);
Console.WriteLine("Age in seconds: {0}", seconds);
var milliSeconds = DateCalcs.MilliSecondDiff(start, finish);
Console.WriteLine("Age in milliseconds: {0}", milliSeconds);

var AgeString = string.Format("{0}yr, {1}mo, {2}d, {3}h, {4}m, {5}s, {6}ms",
    DateCalcs.YearDiff(start, finish),
    DateCalcs.MonthPartDiff(start, finish),
    DateCalcs.DayPartDiff(start, finish),
    DateCalcs.HourPartDiff(start, finish),
    DateCalcs.MinutePartDiff(start, finish),
    DateCalcs.SecondPartDiff(start, finish),
    DateCalcs.MilliSecondPartDiff(start, finish)
    );

Console.WriteLine("Or {0}", AgeString);

Который только что вернулся

Age in years: 46
Age in months: 560
Age in days: 17073
Age in hours: 409771
Age in minutes: 24586290
Age in seconds: 1475177401
Age in milliseconds: -2147483648
Or 46yr, 8mo, 28d, 19h, 30m, 1s, 792ms
0 голосов
/ 11 июня 2013

Попробуйте это

    public string YearsMonthsDaysDiff(DateTime dateFrom, DateTime dateTo)
    {
        Int32 mD = DateTime.DaysInMonth(dateTo.Year, dateTo.AddMonths(-1).Month); //first check out days in month before dateTo month
        Int32 D1 = dateFrom.Day;
        Int32 M1 = dateFrom.Month;
        Int32 Y1 = dateFrom.Year;
        Int32 D2 = dateTo.Day;
        Int32 M2 = dateTo.Month;
        Int32 Y2 = dateTo.Year;

        // Substract each datetime components accordingly
        D2 -= D1;
        M2 -= M1;
        Y2 -= Y1;
        if (D2 < 0)
        {
            D2 += mD;// D2 is less then D1, then add mD
            M2 -= 1; // but, substract 1 from M2 
        }
        if (M2 < 0)
        {
            M2 += 12; // if M2 is less then M1, then add with 12
            Y2 -= 1; // but substract 1 from Y2 
        }
        return Y2.ToString("## years ") + M2.ToString("##  months ") + D2.ToString("## days");
    }

у меня нормально работает

0 голосов
/ 29 июня 2011

Вы можете использовать класс DateDiff библиотеки Time Period для .NET :

// ----------------------------------------------------------------------
public void DateDiffSample()
{
  DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
  Console.WriteLine( "Date1: {0}", date1 );
  // > Date1: 08.11.2009 07:13:59
  DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
  Console.WriteLine( "Date2: {0}", date2 );
  // > Date2: 20.03.2011 19:55:28

  DateDiff dateDiff = new DateDiff( date1, date2 );

  // differences
  Console.WriteLine( "DateDiff.Years: {0}", dateDiff.Years );
  // > DateDiff.Years: 1
  Console.WriteLine( "DateDiff.Quarters: {0}", dateDiff.Quarters );
  // > DateDiff.Quarters: 5
  Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
  // > DateDiff.Months: 16
  Console.WriteLine( "DateDiff.Weeks: {0}", dateDiff.Weeks );
  // > DateDiff.Weeks: 70
  Console.WriteLine( "DateDiff.Days: {0}", dateDiff.Days );
  // > DateDiff.Days: 497
  Console.WriteLine( "DateDiff.Weekdays: {0}", dateDiff.Weekdays );
  // > DateDiff.Weekdays: 71
  Console.WriteLine( "DateDiff.Hours: {0}", dateDiff.Hours );
  // > DateDiff.Hours: 11940
  Console.WriteLine( "DateDiff.Minutes: {0}", dateDiff.Minutes );
  // > DateDiff.Minutes: 716441
  Console.WriteLine( "DateDiff.Seconds: {0}", dateDiff.Seconds );
  // > DateDiff.Seconds: 42986489

  // elapsed
  Console.WriteLine( "DateDiff.ElapsedYears: {0}", dateDiff.ElapsedYears );
  // > DateDiff.ElapsedYears: 1
  Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
  // > DateDiff.ElapsedMonths: 4
  Console.WriteLine( "DateDiff.ElapsedDays: {0}", dateDiff.ElapsedDays );
  // > DateDiff.ElapsedDays: 12
  Console.WriteLine( "DateDiff.ElapsedHours: {0}", dateDiff.ElapsedHours );
  // > DateDiff.ElapsedHours: 12
  Console.WriteLine( "DateDiff.ElapsedMinutes: {0}", dateDiff.ElapsedMinutes );
  // > DateDiff.ElapsedMinutes: 41
  Console.WriteLine( "DateDiff.ElapsedSeconds: {0}", dateDiff.ElapsedSeconds );
  // > DateDiff.ElapsedSeconds: 29
} // DateDiffSample
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...