รับวันแรกและวันสุดท้ายของเดือนก่อนหน้าใน c #


140

ฉันไม่สามารถนึกถึงสายการบินหนึ่งหรือสองสายที่ง่ายที่จะได้รับเดือนก่อนหน้าในวันแรกและวันสุดท้าย

ฉันเป็น LINQ-ifying เป็นเว็บแอปสำรวจและพวกเขาบีบข้อกำหนดใหม่ใน

แบบสำรวจต้องรวมคำขอบริการทั้งหมดสำหรับเดือนก่อนหน้า ดังนั้นถ้าวันที่ 15 เมษายนฉันต้องการรหัสประจำตัวของ Marches ทั้งหมด

var RequestIds = (from r in rdc.request 
                  where r.dteCreated >= LastMonthsFirstDate && 
                  r.dteCreated <= LastMonthsLastDate 
                  select r.intRequestId);

ฉันไม่สามารถนึกถึงวันที่ได้อย่างง่ายดายหากไม่มีสวิตช์ นอกเสียจากว่าฉันตาบอดและมองเห็นวิธีการภายในของการทำเช่นนั้น

คำตอบ:


304
var today = DateTime.Today;
var month = new DateTime(today.Year, today.Month, 1);       
var first = month.AddMonths(-1);
var last = month.AddDays(-1);

ในบรรทัดถ้าคุณต้องการหนึ่งหรือสองบรรทัด


2
IIRC DateTime วันนี้เป็นการโทรที่ค่อนข้างแพงดังนั้นคุณควรเก็บค่าไว้ในตัวแปรก่อน คำตอบอยู่แล้วดี :)
ลีอันโดรโลเปซ

2
@andleer นี่เป็นห้องสมุดที่ดีซึ่งทำงานได้เหมือนที่คุณพูดถึงfluentdatetime.codeplex.com
Matthew Lock

@MatthewLock ดูเหมือนว่าลิงก์จะใช้งานไม่ได้
Guillermo Gutiérrez

1
@ guillegr123 ตอนนี้ที่ github github.com/FluentDateTime/FluentDateTimeและ Nuget nuget.org/packages/FluentDateTime
Matthew Lock

2
ฉันอยากจะชี้ให้เห็นว่าหากรายการถูกเก็บไว้โดยใช้เต็ม datetime แบบสอบถามนี้อาจล้มเหลวในการดึงใด ๆ ที่เริ่มต้นหลังจาก 12:00 น. ในวันสุดท้ายของเดือน คุณสามารถแก้ปัญหานี้ได้โดยเปลี่ยนบรรทัดสุดท้ายเพื่ออ่าน var last = month.AddTicks (-1);
SixOThree

23

วิธีที่ฉันเคยทำในอดีตคือวันแรกของเดือนนี้

dFirstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );

จากนั้นลบหนึ่งวันเพื่อให้สิ้นเดือนที่แล้ว

dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1);

จากนั้นลบเดือนเพื่อให้ได้วันแรกของเดือนก่อน

dFirstDayOfLastMonth = dFirstDayOfThisMonth.AddMonths(-1);

4
+1 แต่ถ้าพูดให้คล่องคุณจะประเมิน DateTime ได้ดีขึ้นวันนี้หนึ่งครั้งและเก็บไว้ในตัวแปรท้องถิ่น หากรหัสของคุณเริ่มต้นดำเนินการเป็นนาโนวินาทีก่อนเที่ยงคืนการโทรไปยัง DateTime สองครั้งติดต่อกันอาจส่งคืนค่าที่แตกต่างกัน
โจ

ใช่ขอบคุณพวกคุณทุกคนถูกต้องแม้แต่คนอวดรู้แก้ไขข้อผิดพลาด
MikeW

ดีให้คอมไพเลอร์จะอวดความรู้น้อยที่จะคุณ :)
Maksym Gontar

1
upvoted ตามที่ได้ถูกเปรียบเทียบreturn date.AddDays(-(date.Day-1))กับreturn new DateTime(date.Year, date.Month, 1);และประสิทธิภาพของการแสดงซ้ำมากกว่า 2000 ครั้งแรกนั้นดีกว่า (923ms ใหม่ขึ้นกับ 809ms ที่ส่งคืนวัตถุเดียวกัน)
Terry_Brown


9
DateTime LastMonthLastDate = DateTime.Today.AddDays(0 - DateTime.Today.Day);
DateTime LastMonthFirstDate = LastMonthLastDate.AddDays(1 - LastMonthLastDate.Day);

DateTime.Today.Days -> 'System.DateTime' ไม่มีคำจำกัดความสำหรับ 'Days' ...
andleer

5

ฉันใช้หนึ่งซับง่ายนี้

public static DateTime GetLastDayOfPreviousMonth(this DateTime date)
{
    return date.AddDays(-date.Day);
}

ระวังให้ดีว่ามันยังคงเวลา


1
สิ่งที่ฉันต้องการแสดงออกอย่างกระชับฉันสามารถใช้ภายในไตรภาค ขอบคุณ!
Joe Ballard

4

วิธีการที่ใช้วิธีการขยาย:

class Program
{
    static void Main(string[] args)
    {
        DateTime t = DateTime.Now;

        DateTime p = t.PreviousMonthFirstDay();
        Console.WriteLine( p.ToShortDateString() );

        p = t.PreviousMonthLastDay();
        Console.WriteLine( p.ToShortDateString() );


        Console.ReadKey();
    }
}


public static class Helpers
{
    public static DateTime PreviousMonthFirstDay( this DateTime currentDate )
    {
        DateTime d = currentDate.PreviousMonthLastDay();

        return new DateTime( d.Year, d.Month, 1 );
    }

    public static DateTime PreviousMonthLastDay( this DateTime currentDate )
    {
        return new DateTime( currentDate.Year, currentDate.Month, 1 ).AddDays( -1 );
    }
}

ดูลิงค์นี้ http://www.codeplex.com/fluentdatetime สำหรับส่วนขยาย DateTime ที่ได้รับแรงบันดาลใจ


3

กรณีการใช้งานที่ยอมรับในอีคอมเมิร์ซคือวันหมดอายุบัตรเครดิต MM / yy ลบหนึ่งวินาทีแทนหนึ่งวัน มิฉะนั้นจะปรากฏบัตรหมดอายุทั้งวันสุดท้ายของเดือนที่หมดอายุ

DateTime expiration = DateTime.Parse("07/2013");
DateTime endOfTheMonthExpiration = new DateTime(
  expiration.Year, expiration.Month, 1).AddMonths(1).AddSeconds(-1);

1

หากมีโอกาสใดที่ชุดข้อมูลของคุณไม่ได้เป็นวันที่ในปฏิทินที่เข้มงวดคุณควรพิจารณาใช้การเปรียบเทียบการยกเว้นวันที่ ...

DateTime now = DateTime.Now;
DateTime thisMonth = new DateTime(now.Year, now.Month, 1);
DateTime lastMonth = thisMonth.AddMonths(-1);

var RequestIds = rdc.request
  .Where(r => lastMonth <= r.dteCreated)
  .Where(r => r.dteCreated < thisMonth)
  .Select(r => r.intRequestId);

1
DateTime now = DateTime.Now;
int prevMonth = now.AddMonths(-1).Month;
int year = now.AddMonths(-1).Year;
int daysInPrevMonth = DateTime.DaysInMonth(year, prevMonth);
DateTime firstDayPrevMonth = new DateTime(year, prevMonth, 1);
DateTime lastDayPrevMonth = new DateTime(year, prevMonth, daysInPrevMonth);
Console.WriteLine("{0} {1}", firstDayPrevMonth.ToShortDateString(),
  lastDayPrevMonth.ToShortDateString());

1
จะทำอย่างไรถ้า DateTime ตอนนี้ให้ผล 2009-01-31 สำหรับการโทรครั้งแรกและ 2009-02-01 สำหรับการโทรครั้งที่สอง?
Amy B

1

นี่คือคำตอบของ Mike W:

internal static DateTime GetPreviousMonth(bool returnLastDayOfMonth)
{
    DateTime firstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );
    DateTime lastDayOfLastMonth = firstDayOfThisMonth.AddDays (-1);
    if (returnLastDayOfMonth) return lastDayOfLastMonth;
    return firstDayOfThisMonth.AddMonths(-1);
}

คุณสามารถเรียกมันว่า:

dateTimePickerFrom.Value = GetPreviousMonth(false);
dateTimePickerTo.Value = GetPreviousMonth(true);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.