ความแตกต่างระหว่าง System.DateTime.Now และ System.DateTime.Today


127

ใครสามารถอธิบายความแตกต่างระหว่างSystem.DateTime.NowและSystem.DateTime.Todayใน C # .NET? ข้อดีข้อเสียของแต่ละข้อถ้าเป็นไปได้

คำตอบ:


179

DateTime.Nowส่งคืนDateTimeค่าที่ประกอบด้วยวันที่และเวลาท้องถิ่นของคอมพิวเตอร์ที่รหัสกำลังทำงานอยู่ ได้DateTimeKind.Localกำหนดให้กับKindทรัพย์สินของตน เทียบเท่ากับการเรียกสิ่งต่อไปนี้:

  • DateTime.UtcNow.ToLocalTime()
  • DateTimeOffset.UtcNow.LocalDateTime
  • DateTimeOffset.Now.LocalDateTime
  • TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
  • TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)

DateTime.Todayส่งคืนDateTimeค่าที่มีส่วนประกอบของปีเดือนและวันเดียวกันกับนิพจน์ใด ๆ ข้างต้น แต่มีการตั้งค่าส่วนประกอบของเวลาเป็นศูนย์ นอกจากนี้ยังมีDateTimeKind.LocalในKindทรัพย์สิน เทียบเท่ากับสิ่งต่อไปนี้:

  • DateTime.Now.Date
  • DateTime.UtcNow.ToLocalTime().Date
  • DateTimeOffset.UtcNow.LocalDateTime.Date
  • DateTimeOffset.Now.LocalDateTime.Date
  • TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local).Date
  • TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local).Date

โปรดทราบว่าภายในนาฬิกาของระบบอยู่ในรูปของ UTC ดังนั้นเมื่อคุณเรียกDateTime.Nowใช้ครั้งแรกให้รับเวลา UTC (ผ่านGetSystemTimeAsFileTimeฟังก์ชันใน Win32 API) จากนั้นจะแปลงค่าเป็นเขตเวลาท้องถิ่น (จึงDateTime.Now.ToUniversalTime()มีราคาแพงกว่าDateTime.UtcNow)

นอกจากนี้โปรดทราบว่าDateTimeOffset.Now.DateTimeจะมีค่าที่คล้ายกันDateTime.Nowแต่จะมีDateTimeKind.Unspecifiedมากกว่าDateTimeKind.Local- ซึ่งอาจนำไปสู่ข้อผิดพลาดอื่น ๆ ขึ้นอยู่กับสิ่งที่คุณทำกับมัน

ดังนั้นคำตอบง่ายๆก็คือว่าเทียบเท่ากับDateTime.Today แต่ IMHO - คุณไม่ควรใช้อย่างใดอย่างหนึ่งหรือเทียบเท่าข้างต้นDateTime.Now.Date

เมื่อคุณถามDateTime.Nowคุณกำลังขอค่าของนาฬิกาปฏิทินภายในของคอมพิวเตอร์ที่รหัสกำลังทำงานอยู่ แต่สิ่งที่คุณได้รับกลับไม่มีข้อมูลเกี่ยวกับนาฬิกาเรือนนั้นเลย! DateTime.Now.Kind == DateTimeKind.Localที่ดีที่สุดที่คุณจะได้รับคือ แต่มันเป็นของใคร? ข้อมูลนั้นจะหายไปทันทีที่คุณทำอะไรกับค่าเช่นเก็บไว้ในฐานข้อมูลแสดงบนหน้าจอหรือส่งโดยใช้บริการเว็บ

หากโซนเวลาท้องถิ่นของคุณต่อกฎใด ๆ เงินฝากออมทรัพย์ในเวลากลางวัน, DateTime.Nowคุณไม่ได้รับที่กลับมาข้อมูลจาก ในช่วงเวลาที่คลุมเครือเช่นในช่วงการเปลี่ยนแปลง "ถอยกลับ" คุณจะไม่รู้ว่าช่วงเวลาใดที่เป็นไปได้ที่สอดคล้องกับค่าที่คุณดึงDateTime.Nowมา ตัวอย่างเช่นสมมติว่าระบบของคุณตั้งค่าเป็นเขตเวลาMountain Time (US & Canada)และคุณขอDateTime.Nowในช่วงหัวค่ำของวันที่ 3 พฤศจิกายน 2013 ผลลัพธ์2013-11-03 01:00:00หมายความว่าอย่างไร มีช่วงเวลาสองช่วงเวลาที่แสดงโดยวันที่และเวลาปฏิทินเดียวกันนี้ ถ้าฉันจะส่งค่านี้ไปให้คนอื่นพวกเขาคงไม่รู้ว่าฉันหมายถึงอันไหน โดยเฉพาะอย่างยิ่งถ้าพวกเขาอยู่ในเขตเวลาที่กฎแตกต่างกัน

สิ่งที่ดีที่สุดที่คุณสามารถทำได้คือใช้DateTimeOffsetแทน:

// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;

ตอนนี้สำหรับสถานการณ์เดียวกันที่ฉันอธิบายไว้ข้างต้นฉันได้รับค่า2013-11-03 01:00:00 -0600ก่อนการเปลี่ยนแปลงหรือ2013-11-03 01:00:00 -0700หลังการเปลี่ยนแปลง ใครก็ตามที่ดูค่าเหล่านี้สามารถบอกได้ว่าฉันหมายถึงอะไร

ฉันเขียนบล็อกโพสต์เกี่ยวกับเรื่องนี้ โปรดอ่าน - กรณีกับ DateTime.Now

นอกจากนี้ยังมีสถานที่บางแห่งในโลกนี้ (เช่นบราซิล) ที่การเปลี่ยนแปลงแบบ "ก้าวไปข้างหน้า" เกิดขึ้นตรงกับเวลาเที่ยงคืน นาฬิกาเปิดเวลา 23.59 น. - 01:00 น. นั่นหมายความว่ามูลค่าที่คุณได้รับDateTime.Todayในวันนั้นไม่มีอยู่จริง! แม้ว่าคุณจะใช้DateTimeOffset.Now.Dateคุณจะได้รับผลลัพธ์เดียวกันและคุณยังคงมีปัญหานี้ เป็นเพราะตามปกติแล้วไม่มีสิ่งที่เรียกว่าDateวัตถุใน. Net ดังนั้นไม่ว่าคุณจะได้รับมูลค่าอย่างไรเมื่อคุณตัดเวลาออกไปคุณต้องจำไว้ว่ามันไม่ได้แสดงถึง "เที่ยงคืน" จริงๆแม้ว่านั่นจะเป็นคุณค่าที่คุณกำลังดำเนินการอยู่ก็ตาม

หากคุณต้องการการแก้ปัญหาที่ถูกต้องอย่างเต็มที่ในการแก้ไขปัญหานี้จริงๆวิธีที่ดีที่สุดคือการใช้NodaTime LocalDateระดับอย่างถูกต้องหมายถึงวันโดยไม่ต้องเวลา คุณสามารถรับวันที่ปัจจุบันสำหรับโซนเวลาใดก็ได้รวมถึงเขตเวลาของระบบท้องถิ่น:

using NodaTime;
...

Instant now = SystemClock.Instance.Now;

DateTimeZone zone1 = DateTimeZoneProviders.Tzdb.GetSystemDefault();
LocalDate todayInTheSystemZone = now.InZone(zone1).Date;

DateTimeZone zone2 = DateTimeZoneProviders.Tzdb["America/New_York"];
LocalDate todayInTheOtherZone = now.InZone(zone2).Date;

หากคุณไม่ต้องการใช้ Noda Time ตอนนี้มีอีกทางเลือกหนึ่ง ผมเคยมีส่วนทำให้การดำเนินการของวัตถุวันเท่านั้นที่จะ.Net CoreFX Labโครงการ คุณสามารถค้นหาSystem.Timeวัตถุแพ็กเกจได้ในฟีด MyGet เมื่อเพิ่มลงในโครงการของคุณแล้วคุณจะพบว่าคุณสามารถทำสิ่งใดสิ่งหนึ่งต่อไปนี้:

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);

9
สิ่งที่เกี่ยวกับการใช้DateTime.UtcNowแทนDateTimeOffset.Now?
Samuel Liew

5
DateTime.UtcNowเป็นที่ยอมรับหากคุณสามารถระบุในใบสมัครหรือข้อมูลจำเพาะของคุณว่าค่าเป็น UTC (ฉันชอบเรียกฟิลด์หรือคุณสมบัติว่าMyDateUtcแทนที่จะเป็นMyDate- แต่นั่นเป็นเพียงแค่ไอซิ่งบนเค้ก) หากคุณไม่สามารถถ่ายทอดมันในข้อมูลจำเพาะหรือชื่อฟิลด์คุณDateTimeOffset.UtcNowสามารถใช้เพื่อให้แน่ใจว่าศูนย์ออฟเซ็ตได้รับการถ่ายทอด ด้วยค่าวันที่และเวลา
Matt Johnson-Pint

พวกเขาไม่เท่ากัน วันนี้มีเวลา 00:00:00 น.
James Wilkins

@JamesWilkins - ไม่แน่ใจว่าคุณกำลังทำอะไรอยู่ ก็DateTime.Now.Dateเช่นกัน
Matt Johnson-Pint

@MattJohnson คำถามคือการถามความแตกต่างระหว่าง DateTime.Today และ DateTime.Now ไม่ใช่ DateTime.Today และ DateTime.Now.Date
David Anderson

85

เวลา. .Nowรวม 09:23:12 หรืออะไรก็ได้; .Todayเป็นส่วนของวันที่เท่านั้น (เวลา 00:00:00 น. ของวันนั้น)

ดังนั้นใช้.Nowถ้าคุณต้องการรวมเวลาและ.Todayถ้าคุณต้องการวันที่!

.Today โดยพื้นฐานแล้วจะเหมือนกับ .Now.Date


27
... และใช้UtcNowเว้นแต่คุณต้องการเขตเวลาท้องถิ่นของระบบจริงๆ (โดยเฉพาะบนเว็บแอปที่มักจะเป็นตัวเลือกที่ผิด)
Jon Skeet

22

คุณสมบัติส่งกลับวันและเวลาปัจจุบันตัวอย่างเช่นDateTime.Now2011-07-01 10:09.45310

DateTime.Todayคุณสมบัติส่งกลับวันที่ปัจจุบันมี compnents 2011-07-01 00:00.00000เวลาที่กำหนดเป็นศูนย์ตัวอย่างเช่น

DateTime.TodayคุณสมบัติจริงจะดำเนินการกลับมาDateTime.Now.Date:

public static DateTime Today {
  get {
    DateTime now = DateTime.Now;
    return now.Date;
  }
}

9

DateTime.Todayหมายถึงวันที่ระบบปัจจุบันที่มีส่วนชุดเวลาที่จะ 00:00:00

และ

DateTime.Nowแสดงวันที่และเวลาของระบบปัจจุบัน


2
เป็นเพียงการสังเกต ... เอกสาร 1.1 มีรายละเอียดน้อยกว่าเอกสาร 4.0 บางทีอาจจะดีกว่าที่จะเชื่อมโยงไปยัง vLatest?
Marc Gravell

3
@megaperlz: ตอนนี้คุณกำลังเชื่อมโยงกับ 4.0 แทนที่จะเป็น vLatest ลิงก์ VLatest สามารถทำได้โดยการลบไฟล์(v=VS.100).
Brian

6

ฉันคิดว่าจะเพิ่มลิงก์เหล่านี้ -

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

 public static DateTime Today
    {
      get
      {
        return DateTime.Now.Date;   // It returns the date part of Now

        //Date Property
       // returns same date as this instance, and the time value set to 12:00:00 midnight (00:00:00) 
      }
    }


    private const long TicksPerMillisecond = 10000L;
    private const long TicksPerDay = 864000000000L;
    private const int MillisPerDay = 86400000;

    public DateTime Date
    {
       get
      {
        long internalTicks = this.InternalTicks; // Date this instance is converted to Ticks 
        return new DateTime((ulong) (internalTicks - internalTicks % 864000000000L) | this.InternalKind);  
// Modulo of TicksPerDay is subtracted - which brings the time to Midnight time 
      }
    }


     public static DateTime Now
        {
          get
          {
           /* this is why I guess Jon Skeet is recommending to use  UtcNow as you can see in one of the above comment*/
            DateTime utcNow = DateTime.UtcNow;


            /* After this i guess it is Timezone conversion */
            bool isAmbiguousLocalDst = false;
            long ticks1 = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousLocalDst).Ticks;
            long ticks2 = utcNow.Ticks + ticks1;
            if (ticks2 > 3155378975999999999L)
              return new DateTime(3155378975999999999L, DateTimeKind.Local);
            if (ticks2 < 0L)
              return new DateTime(0L, DateTimeKind.Local);
            else
              return new DateTime(ticks2, DateTimeKind.Local, isAmbiguousLocalDst);
          }
        }

5
DateTime dt = new DateTime();// gives 01/01/0001 12:00:00 AM
DateTime dt = DateTime.Now;// gives today date with current time
DateTime dt = DateTime.Today;// gives today date and 12:00:00 AM time

1

DateTime.TodayคือDateTime.Nowตั้งเวลาเป็นศูนย์

สิ่งสำคัญคือต้องสังเกตว่ามีความแตกต่างระหว่างค่า DateTime ซึ่งแสดงถึงจำนวนเห็บที่ผ่านไปตั้งแต่เที่ยงคืนของวันที่ 1 มกราคม 0000 และการแสดงสตริงของค่า DateTime นั้นซึ่งแสดงค่าวันที่และเวลาใน a รูปแบบเฉพาะวัฒนธรรม: https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx

DateTime.Now.Ticksคือเวลาจริงที่จัดเก็บโดย. net (โดยพื้นฐานแล้วคือเวลา UTC) ส่วนที่เหลือเป็นเพียงการแสดง (ซึ่งสำคัญสำหรับวัตถุประสงค์ในการแสดงผล)

หากKindคุณสมบัติDateTimeKind.Localนั้นมีข้อมูลโซนเวลาของคอมพิวเตอร์ในระบบโดยปริยาย เมื่อส่งผ่านบริการเว็บ. net ค่า DateTime จะถูกทำให้เป็นอนุกรมตามค่าเริ่มต้นโดยมีข้อมูลโซนเวลารวมอยู่ด้วยเช่น 2008-10-31T15: 07: 38.6875000-05: 00 และคอมพิวเตอร์ในเขตเวลาอื่นยังสามารถทราบได้อย่างชัดเจนว่าเวลาคืออะไร ถูกอ้างถึง

ดังนั้นการใช้ DateTime.Now และ DateTime.Today ก็โอเคอย่างสมบูรณ์แบบ

โดยปกติคุณจะเริ่มประสบปัญหาเมื่อคุณเริ่มสับสนในการแทนค่าสตริงกับค่าจริงและพยายาม "แก้ไข" DateTime เมื่อมันไม่เสีย


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