programing

지정된 DateTime 개체를 사용하여 월의 첫 번째 및 마지막 날 가져오기

elecom 2023. 5. 23. 21:24
반응형

지정된 DateTime 개체를 사용하여 월의 첫 번째 및 마지막 날 가져오기

저는 주어진 날짜가 있는 달의 첫 번째 날과 마지막 날을 받고 싶습니다.날짜는 UI 필드의 값에서 가져옵니다.

내가 시간 선택기를 사용하고 있다면 나는 말할 수 있습니다.

var maxDay = dtpAttendance.MaxDate.Day;

하지만 DateTime 개체에서 가져오려고 합니다.그래서 내가 이걸 가지고 있다면,

DateTime dt = DateTime.today;

월의 첫 번째 날과 마지막 날을 가져오는 방법dt?

DateTime 구조체는 값 범위가 아닌 하나의 값만 저장합니다. MinValue그리고.MaxValue는 static fields로, 정필는인스대에해가값다의 합니다.DateTime 인스턴스.DateTime은 관가있습다니계와 관련이 .DateTime타자를 치다

권장 판독값: 정적(C# 기준)

업데이트: 월 범위 가져오기:

DateTime date = ...
var firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);

업데이트: 댓글에서 (@KarlGjertsen & @SergeyBerezovsky)

DateTime date = ...
var firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddSeconds(-1);
//OR
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddTicks(-1);

이것은 @Sergey와 @Steffen의 답변에 대한 더 긴 논평입니다.과거에 비슷한 코드를 직접 작성한 적이 있어서 명확성도 중요하다는 것을 기억하면서 가장 성능이 좋은 것을 확인하기로 했습니다.

결과

다음은 1,000만 번 반복에 대한 테스트 실행 결과의 예입니다.

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# Program mode)를 사용하여 컴파일러 최적화를 켠 상태에서 테스트를 실행했습니다.다음은 명확성과 편의성을 위해 테스트된 코드를 확장 방법은 다음과 같습니다.

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_AddMethod에 대한 명백한 패배자였습니다.LastDayOfMonth_AddMethodWithDaysInMonth,LastDayOfMonth_NewMethod그리고.LastDayOfMonth_NewMethodWithReuseOfExtMethod가장 빠른 세 개 사이에는 별 것이 없기 때문에 개인적인 취향에 따라 달라집니다.저는 다음의 선명도를 선택합니다.LastDayOfMonth_NewMethodWithReuseOfExtMethod다른유확한방재사수용있다습니할을법. 가 더 기꺼이 하겠습니다.IMHO의 의도가 더 명확하고 적은 공연비를 기꺼이 받아들이겠습니다.

LastDayOfMonth_SpecialCase했을 수 월의 첫 날짜를 하고 추가 하는 것으로 합니다.DateTime.DaysInMonth결과를 얻기 위해.이것은 당신이 예상하는 것처럼 다른 버전보다 빠르지만, 당신이 속도를 절실히 필요로 하지 않는 한, 저는 당신의 무기에 이 특별한 사례를 두는 것이 무슨 의미가 있는지 모르겠습니다.

결론

다음은 제가 선택한 확장 방법 클래스이며 일반적으로 @Steffen과 동의합니다.

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

여기까지 왔다면 시간 내주셔서 감사합니다!재미있었어요 :).이 알고리즘에 대한 다른 제안이 있으면 의견을 제시해 주십시오.

월 범위를 받는 중입니다.Net API(다른 방법일 뿐):

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

"Last day of month실제로는 "입니다.First day of *next* month, minus 1다음은 "DaysInMonth" 메서드가 필요 없는 사용 방법입니다.

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

public static DateTime LastDayOfMonth(this DateTime value)
{
    return value.FirstDayOfMonth()
        .AddMonths(1)
        .AddMinutes(-1);
}

는 사: 는이하유입니다.AddMinutes(-1),것은 아니다.AddDays(-1)일반적으로 특정 날짜 기간에 대한 보고를 위해 이러한 날짜 함수가 필요하고, 특정 기간에 대한 보고서를 작성할 때 "종료 날짜"는 실제로 다음과 같아야 하기 때문입니다.Oct 31 2015 23:59:59따라서 지난달 마지막 날의 모든 데이터를 포함하여 보고서가 올바르게 작동합니다.

즉, 여기서 "이달의 마지막 순간"을 얻게 됩니다.마지막 날이 아닙니다.

좋아요, 이제 입 다물어요.

DateTime dCalcDate = DateTime.Now;
dtpFromEffDate.Value = new DateTime(dCalcDate.Year, dCalcDate.Month, 1);
dptToEffDate.Value = new DateTime(dCalcDate.Year, dCalcDate.Month, DateTime.DaysInMonth(dCalcDate.Year, dCalcDate.Month));

여기서 현재 달의 첫 번째 날에 대해 해당 날짜에서 하루를 삭제하는 것보다 한 달을 추가할 수 있습니다.

DateTime now = DateTime.Now;
var startDate = new DateTime(now.Year, now.Month, 1);
var endDate = startDate.AddMonths(1).AddDays(-1);

만약 당신이 날짜만 신경 쓴다면.

var firstDay = new DateTime(date.Year, date.Month, 1, 0, 0, 0, date.Kind);
var lastDay = new DateTime(date.Year, date.Month, 1, 0, 0, 0, date.Kind).AddMonths(1).AddDays(-1);

시간을 보존하려면

var firstDay = new DateTime(date.Year, date.Month, 1, date.Hour, date.Minute, date.Second, date.Kind);
var lastDay = new DateTime(date.Year, date.Month, 1, date.Hour, date.Minute, date.Second, date.Kind).AddMonths(1).AddDays(-1);

사용해 보십시오.

string strDate = DateTime.Now.ToString("MM/01/yyyy");

여기서 승인된 답변은 DateTime 인스턴스의 종류를 고려하지 않습니다.예를 들어, 원래 DateTime 인스턴스가 UTC Kind인 경우 새 DateTime 인스턴스를 만들면 알 수 없는 Kind 인스턴스가 생성되고 서버 설정에 따라 로컬 시간으로 처리됩니다.따라서 월의 첫 번째와 마지막 날짜를 얻는 더 적절한 방법은 다음과 같습니다.

var now = DateTime.UtcNow;
var first = now.Date.AddDays(-(now.Date.Day - 1));
var last = first.AddMonths(1).AddTicks(-1);

이렇게 하면 DateTime 인스턴스의 원래 Kind가 보존됩니다.

저는 이것을 제 대본에 사용했지만 날짜만 다듬고 시간이 없는 전체 날짜가 필요했습니다.

public DateTime GetLastDayOfTheMonth()
{
    int daysFromNow = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month) - (int)DateTime.Now.Day;
    return DateTime.Now.AddDays(daysFromNow);
}

페르시아 문화를 위하여

PersianCalendar pc = new PersianCalendar();            

var today = pc.GetDayOfMonth(DateTime.Now);
var firstDayOfMonth = pc.GetDayOfMonth(DateTime.Now.AddDays(-(today-1)));
var lastDayOfMonth = pc.GetDayOfMonth(DateTime.Now.AddMonths(1).AddDays(-today));            
Console.WriteLine("First day "+ firstDayOfMonth);
Console.WriteLine("Last day " + lastDayOfMonth);

당신은 할 수 있어요.

DateTime dt = DateTime.Now; 
DateTime firstDayOfMonth = new DateTime(dt.Year, date.Month, 1);
DateTime lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);

한 번 해보세요.기본적으로 경과된 일 수를 계산합니다.DateTime.Now그런 다음 이 값에서 하나를 뺀 다음 새 값을 사용하여 현재 달의 첫 번째 값을 찾습니다.거기서부터 그것을 사용합니다.DateTime 및용을 합니다..AddMonths(-1)지난 달 1일에 받을 수 있습니다.

지난달의 마지막 날을 얻는 은 기본적으로 한 달의 일 수에 1을 더하고 값을 뺀 것을 제외하고는 동일한 작업을 수행합니다.DateTime.Now.AddDays이전 달의 마지막 날을 제공합니다.

int NumberofDays = DateTime.Now.Day;
int FirstDay = NumberofDays - 1;
int LastDay = NumberofDays + 1;
DateTime FirstofThisMonth = DateTime.Now.AddDays(-FirstDay);
DateTime LastDayOfLastMonth = DateTime.Now.AddDays(-LastDay);
DateTime CheckLastMonth = FirstofThisMonth.AddMonths(-1);

이 작업은 현재 월을 잊어버린 첫날에 수행할 수 있습니다.

DateTime.Now.AddDays(-(DateTime.Now.Day-1))

값을 할당합니다.

다음과 같이:

dateEndEdit.EditValue = DateTime.Now;
dateStartEdit.EditValue = DateTime.Now.AddDays(-(DateTime.Now.Day-1));

DateTime 클래스의 인스턴스를 만듭니다.

DateTime dateTime = DateTime.Now;

만약 당신이 달의 마지막 날을 얻고 싶다면, 당신은 이것을 할 수 있습니다.

int lastDayOfMonth = DateTime.DaysInMonth(caducidadPuntos.Year, caducidadPuntos.Month);

만약 당신이 그 달의 첫 날을 얻고 싶다면, 당신은 이것을 할 수 있습니다.

DateTime firstDayMonth = new DateTime(dateTime.Year, dateTime.Month, 1);

우리는 주어진 날짜의 월의 시작과 끝을 시간을 포함하여 얻을 수 있어야 한다는 요구 조건은 다음과 같습니다.우리는 여기 계신 모든 분들께 감사드리며 위에서 언급한 솔루션을 활용하게 되었고, 이 솔루션을 Util 클래스에 결합하여 마지막 밀리초까지 주어진 월 및 연도 번호 조합을 얻을 수 있었습니다.다른 사람에게 도움이 될 경우 우리가 앞으로 나아갈 것을 포함해서 말입니다.

활용도:

public class DateUtil
{
    public static (DateTime startOfMonth, DateTime endOfMonth) GetStartAndEndOfMonth(int month, int year)
    {
        DateTime startOfMonth = GetStartOfMonth(month, year);
        DateTime endOfMonth = GetEndOfMonth(month, year);

        return (startOfMonth, endOfMonth);
    }

    public static DateTime GetStartOfMonth(int month, int year)
    {
        return new DateTime(year, month, 1).Date;
    }

    public static DateTime GetEndOfMonth(int month, int year)
    {
        return new DateTime(year, month, 1).Date.AddMonths(1).AddMilliseconds(-1);
    }
}

용도:

(DateTime startOfMonth, DateTime endOfMonth) = DateUtil.GetStartAndEndOfMonth(2, 2021); // February, 2021

쉬운 방법

Begin = new DateTime(DateTime.Now.Year, DateTime.Now.Month,1).ToShortDateString();
End = new DataFim.Text = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month)).ToShortDateString();
DateTime dCalcDate = DateTime.Now;
var startDate = new DateTime(Convert.ToInt32(Year), Convert.ToInt32(Month), 1);
var endDate = new DateTime(Convert.ToInt32(Year), Convert.ToInt32(Month), DateTime.DaysInMonth((Convert.ToInt32(Year)), Convert.ToInt32(Month)));

언급URL : https://stackoverflow.com/questions/24245523/getting-the-first-and-last-day-of-a-month-using-a-given-datetime-object

반응형