首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用给定的DateTime对象获取一个月的第一天和最后一天

使用给定的DateTime对象获取一个月的第一天和最后一天
EN

Stack Overflow用户
提问于 2014-06-16 22:01:21
回答 16查看 337.2K关注 0票数 243

我想要得到给定日期所在的月份的第一天和最后一天。日期来自UI字段中的值。

如果我使用的是时间选择器,我可以说

代码语言:javascript
复制
var maxDay = dtpAttendance.MaxDate.Day;

但我正在尝试从DateTime对象中获取它。如果我有这个..。

代码语言:javascript
复制
DateTime dt = DateTime.today;

如何从dt获取每月的第一天和最后一天

EN

回答 16

Stack Overflow用户

回答已采纳

发布于 2014-06-16 22:02:09

DateTime结构只存储一个值,而不是值的范围。MinValueMaxValue是静态字段,它们包含DateTime结构实例的可能值范围。这些字段是静态的,与DateTime的特定实例无关。它们与DateTime类型本身相关。

推荐阅读:static (C# Reference)

更新:获取月份范围:

代码语言:javascript
复制
DateTime date = ...
var firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);
票数 573
EN

Stack Overflow用户

发布于 2015-07-21 20:19:39

这更多的是对@Sergey和@Steffen的答案的长篇评论。我自己以前也写过类似的代码,所以我决定检查一下什么是最performant的,同时也要记住清晰也很重要。

结果

下面是一个1000万次迭代的示例测试运行结果:

代码语言:javascript
复制
2257 ms for FirstDayOfMonth_AddMethod()
2406 ms for FirstDayOfMonth_NewMethod()
6342 ms for LastDayOfMonth_AddMethod()
4037 ms for LastDayOfMonth_AddMethodWithDaysInMonth()
4160 ms for LastDayOfMonth_NewMethod()
4212 ms for LastDayOfMonth_NewMethodWithReuseOfExtMethod()
2491 ms for LastDayOfMonth_SpecialCase()

代码

我使用LINQPad 4 (在C#程序模式下)在打开编译器优化的情况下运行测试。以下是为清晰和方便起见而作为扩展方法分解的测试代码:

代码语言:javascript
复制
public static class DateTimeDayOfMonthExtensions
{
    public static DateTime FirstDayOfMonth_AddMethod(this DateTime value)
    {
        return value.Date.AddDays(1 - value.Day);
    }
    
    public static DateTime FirstDayOfMonth_NewMethod(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, 1);
    }
    
    public static DateTime LastDayOfMonth_AddMethod(this DateTime value)
    {
        return value.FirstDayOfMonth_AddMethod().AddMonths(1).AddDays(-1);
    }
    
    public static DateTime LastDayOfMonth_AddMethodWithDaysInMonth(this DateTime value)
    {
        return value.Date.AddDays(DateTime.DaysInMonth(value.Year, value.Month) - value.Day);
    }
    
    public static DateTime LastDayOfMonth_SpecialCase(this DateTime value)
    {
        return value.AddDays(DateTime.DaysInMonth(value.Year, value.Month) - 1);
    }
    
    public static int DaysInMonth(this DateTime value)
    {
        return DateTime.DaysInMonth(value.Year, value.Month);
    }
    
    public static DateTime LastDayOfMonth_NewMethod(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, DateTime.DaysInMonth(value.Year, value.Month));
    }

    public static DateTime LastDayOfMonth_NewMethodWithReuseOfExtMethod(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, value.DaysInMonth());
    }
}

void Main()
{
    Random rnd = new Random();
    DateTime[] sampleData = new DateTime[10000000];
    
    for(int i = 0; i < sampleData.Length; i++) {
        sampleData[i] = new DateTime(1970, 1, 1).AddDays(rnd.Next(0, 365 * 50));
    }
    
    GC.Collect();
    System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].FirstDayOfMonth_AddMethod();
    }
    string.Format("{0} ms for FirstDayOfMonth_AddMethod()", sw.ElapsedMilliseconds).Dump();
    
    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].FirstDayOfMonth_NewMethod();
    }
    string.Format("{0} ms for FirstDayOfMonth_NewMethod()", sw.ElapsedMilliseconds).Dump();
    
    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_AddMethod();
    }
    string.Format("{0} ms for LastDayOfMonth_AddMethod()", sw.ElapsedMilliseconds).Dump();

    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_AddMethodWithDaysInMonth();
    }
    string.Format("{0} ms for LastDayOfMonth_AddMethodWithDaysInMonth()", sw.ElapsedMilliseconds).Dump();

    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_NewMethod();
    }
    string.Format("{0} ms for LastDayOfMonth_NewMethod()", sw.ElapsedMilliseconds).Dump();

    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_NewMethodWithReuseOfExtMethod();
    }
    string.Format("{0} ms for LastDayOfMonth_NewMethodWithReuseOfExtMethod()", sw.ElapsedMilliseconds).Dump();

    for(int i = 0; i < sampleData.Length; i++) {
        sampleData[i] = sampleData[i].FirstDayOfMonth_AddMethod();
    }
    
    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_SpecialCase();
    }
    string.Format("{0} ms for LastDayOfMonth_SpecialCase()", sw.ElapsedMilliseconds).Dump();
    
}

分析

我对其中一些结果感到惊讶。

尽管FirstDayOfMonth_AddMethod的功能不多,但在测试的大多数运行过程中,它都比FirstDayOfMonth_NewMethod稍微快一些。然而,我认为后者的意图稍微明确一些,所以我更倾向于这样做。

LastDayOfMonth_AddMethodWithDaysInMonthLastDayOfMonth_NewMethodLastDayOfMonth_NewMethodWithReuseOfExtMethod相比,LastDayOfMonth_AddMethod是一个明显的输家。在最快的三个之间,没有太多的东西,所以归根结底是你的个人偏好。我选择了LastDayOfMonth_NewMethodWithReuseOfExtMethod的简洁性,因为它重用了另一个有用的扩展方法。我的意图更明确,我愿意接受较小的性能成本。

LastDayOfMonth_SpecialCase假设您在特殊情况下提供的是月份的第一天,在这种情况下您可能已经计算了该日期,并且它使用带有DateTime.DaysInMonth的add方法来获得结果。正如您所期望的那样,这比其他版本更快,但除非您迫切需要速度,否则我看不出在您的武器库中有这个特殊情况的意义。

结论

下面是一个带有我的选择的扩展方法类,我相信它与@Steffen大体一致:

代码语言:javascript
复制
public static class DateTimeDayOfMonthExtensions
{
    public static DateTime FirstDayOfMonth(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, 1);
    }
    
    public static int DaysInMonth(this DateTime value)
    {
        return DateTime.DaysInMonth(value.Year, value.Month);
    }
    
    public static DateTime LastDayOfMonth(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, value.DaysInMonth());
    }
}

如果你已经走到这一步,谢谢你抽出时间来!这很有趣:()。如果您对这些算法有任何其他建议,请发表评论。

票数 127
EN

Stack Overflow用户

发布于 2015-01-30 08:04:24

使用.Net接口获取月份范围(只是另一种方式):

代码语言:javascript
复制
DateTime date = ...
var firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
var lastDayOfMonth = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
票数 22
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24245523

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档