一起添加两个DateTime对象 [英] Adding two DateTime objects together

查看:137
本文介绍了一起添加两个DateTime对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  DateTime first = new DateTime( 2000,1,1); 
DateTime second = new DateTime(11,2,5,10,10,11);

DateTime result = first.AddYears(second.Year);
DateTime result = first.AddMonths(second.Month);
...

等等...



在这个例子中,我想获得 DateTime(2011,3,6,10,10,11)



编辑



经过密集的头脑风暴,似乎没有什么不同的方式,但为了方便它可以装箱里面的额外的类和运算符+就像在JonSkeet的答案

解决方案

添加两个 DateTime 值。如果你想代表11年,2个月,5天,10小时,10分11秒,那么你应该代表。这不是与0011-02-05T10:10:11相同。特别是,你永远不能添加2个月30天。同样,您永远无法添加一年,因为您不能在日期内的月份和日期值为0。



现在没有BCL类型代表11年[...]的想法,但你可以很容易地创建自己的一个。或者,您可以使用 Noda Time 项目,其中期限正是为此目的:

  var localDateTime = new LocalDate(2000,1,10).AtMidnight(); 
var period = new PeriodBuilder {
Years = 11,Months = 2,Days = 5,
Hours = 10,Minutes = 10,Seconds = 11
} .Build() ;
var result = localDateTime + period;

与此处提供的其他一些答案相反,您不能使用 TimeSpan 为此目的。 TimeSpan 不具有月和年的任何概念,因为它们的长度不同,而 TimeSpan 表示固定蜱数。 (如果你最大的单位是天数,那么你可以使用 TimeSpan ,但以你的例子为例,我假设你需要几个月和几年。)



如果您不想使用Noda Time,我建议您自己伪造一个期间类。这很容易做到 - 例如:

  //未经测试并迅速被黑客入侵。许多更多的API你可能会
//想要,字符串转换,属性等
public sealed class Period
{
private readonly int年,月,日,小时,分钟,秒

public Period(int years,int months,int days,
int hours,int minutes,int seconds)
{
this.years = years;
this.months = months;
this.days = days;
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
}

public static DateTime运算符+(DateTime lhs,Period rhs)
{
//注意:操作顺序在这里很重要。
//考虑1月1日+(1个月和30天)...
//你想要结果是什么?
return lhs.AddYears(rhs.years)
.AddMonths(rhs.months)
.AddDays(rhs.days)
.AddHours(rhs.hours)
.AddMinutes(rhs.minutes)
.AddSeconds(rhs.seconds);
}
}

用法:

  DateTime first = new DateTime(2000,1,1); 
期间秒=新时期(11,2,5,10,10,11);
DateTime result = first + second;

您需要注意 DateTime.Add 将处理不可能的情况 - 例如,添加一个月到1月31日将给你2月28日/ 29日,取决于它是否是一个闰年。



简单的方法我在这里列出了中间价值观,有其缺点,因为截断可能会发生两次(添加几年,然后加上几个月),如果不需要 - 例如2月29日+ 1年+ 1个月可能逻辑上是3月29日,但实际上最终将会是3月28日,因为截止到2月28日将在月底之前发生。



试图找出一个进行日历算术的正确方式是愚蠢难度,特别是在某些人们可能会对正确答案是否有异议。在上述代码中,我选择了简单性和可预测性 - 根据您的实际需求,您可能需要更复杂的一些。


Is there any better way to add one DateTime object to another one, than this:

DateTime first = new DateTime(2000, 1, 1);
DateTime second = new DateTime(11, 2, 5, 10, 10, 11);

DateTime result = first.AddYears(second.Year);
DateTime result = first.AddMonths(second.Month);
...

and so on...

In this example I'd like to get DateTime(2011, 3, 6, 10, 10, 11)

EDIT

After a intensive brainstorm it seems to there's no different way, but to facilitate it can be boxed inside additional class and operator+ just like in JonSkeet's answer

解决方案

It doesn't make sense to add two DateTime values together. If you want to represent "11 years, 2 months, 5 days, 10 hours, 10 minutes and 11 seconds" then you should represent that. That's not the same as 0011-02-05T10:10:11. In particular, you'd never be able to add "2 months and 30 days" for example. Likewise you'd never be able to add just a single year, because you can't have 0 for month and day values within a date.

Now there's no BCL type to represent the idea of "11 years [...]" but you could create your own one reasonably easily. As an alternative, you could use my Noda Time project which has Period for precisely this purpose:

var localDateTime = new LocalDate(2000, 1, 10).AtMidnight();
var period = new PeriodBuilder {
    Years = 11, Months = 2, Days = 5,
    Hours = 10, Minutes = 10, Seconds = 11
}.Build();
var result = localDateTime + period;

Contrary to some other answers provided here, you cannot use TimeSpan for this purpose. TimeSpan doesn't have any concept of months and years, because they vary in length, whereas a TimeSpan represents a fixed number of ticks. (If your largest unit is days, then you're fine to use TimeSpan, but given your example, I assume you need months and years.)

If you don't want to use Noda Time, I'd recommend you fake up a Period-like class yourself. It's easy enough to do - for example:

// Untested and quickly hacked up. Lots more API you'd probably
// want, string conversions, properties etc.
public sealed class Period
{
    private readonly int years, months, days, hours, minutes, seconds;

    public Period(int years, int months, int days,
                  int hours, int minutes, int seconds)
    {
        this.years = years;
        this.months = months;
        this.days = days;
        this.hours = hours;
        this.minutes = minutes;
        this.seconds = seconds;
    }

    public static DateTime operator+(DateTime lhs, Period rhs)
    {
        // Note: order of operations is important here.
        // Consider January 1st + (1 month and 30 days)...
        // what do you want the result to be?
        return lhs.AddYears(rhs.years)
                  .AddMonths(rhs.months)
                  .AddDays(rhs.days)
                  .AddHours(rhs.hours)
                  .AddMinutes(rhs.minutes)
                  .AddSeconds(rhs.seconds);
    }
}

Usage:

DateTime first = new DateTime(2000, 1, 1);
Period second = new Period(11, 2, 5, 10, 10, 11);
DateTime result = first + second;

You need to be aware of how DateTime.Add will handle impossible situations - for example adding a month to January 31st will give you February 28th/29th depending on whether or not it's a leap year.

The simple approach I've listed here, going through intermediate values, has its downsides, because that truncation can happen twice (adding years and then adding months) when it needn't - for example, "February 29th + 1 year + 1 month" might logically be "March 29th" but it will actually end up as "March 28th" as the truncation to February 28th will happen before the month is added.

Trying to work out a "right" way of doing calendrical arithmetic is fiendishly difficult, particularly as in some cases people may disagree about what the "right" answer is. In the above code I've opted for simplicity and predictability - depending on your real requirements, you may need something more complex.

这篇关于一起添加两个DateTime对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆