วิธีจัดการกับเขตเวลาอย่างหรูหรา


140

ฉันมีเว็บไซต์ที่โฮสต์ในเขตเวลาที่แตกต่างจากผู้ใช้ที่ใช้แอปพลิเคชัน นอกจากนี้ผู้ใช้สามารถมีเขตเวลาที่เฉพาะเจาะจง ฉันสงสัยว่าผู้ใช้และแอปพลิเคชั่น SO อื่น ๆ เข้าหาสิ่งนี้อย่างไร ส่วนที่ชัดเจนที่สุดคือภายใน DB วันที่ / เวลาจะถูกเก็บไว้ใน UTC เมื่ออยู่บนเซิร์ฟเวอร์ควรจัดการวันที่ / เวลาทั้งหมดใน UTC อย่างไรก็ตามฉันเห็นปัญหาสามข้อที่ฉันพยายามเอาชนะ:

  1. รับเวลาปัจจุบันใน UTC (แก้ไขได้อย่างง่ายดายด้วยDateTime.UtcNow)

  2. ดึงวันที่ / เวลาจากฐานข้อมูลและแสดงสิ่งเหล่านี้กับผู้ใช้ อาจมีการโทรจำนวนมากที่จะพิมพ์วันที่ในมุมมองที่ต่างกัน ฉันกำลังคิดถึงเลเยอร์บางอย่างระหว่างมุมมองและตัวควบคุมที่สามารถแก้ปัญหานี้ได้ หรือมีวิธีการขยายแบบกำหนดเองในDateTime(ดูด้านล่าง) ข้อเสียที่สำคัญคือทุกครั้งที่ใช้ datetime ในมุมมองต้องใช้วิธีการขยาย!

    JsonResultนอกจากนี้ยังจะเพิ่มความยากลำบากในการใช้สิ่งที่ต้องการ คุณไม่สามารถจะเรียกมันจะต้องมีการJson(myEnumerable) Json(myEnumerable.Select(transformAllDates))AutoMapper อาจช่วยในสถานการณ์นี้ได้ไหม

  3. รับอินพุตจากผู้ใช้ (Local เป็น UTC) ตัวอย่างเช่นการโพสต์แบบฟอร์มด้วยวันที่จะต้องแปลงวันที่เป็น UTC ก่อน ModelBinderสิ่งแรกที่มาถึงใจคือการสร้างที่กำหนดเอง

นี่คือส่วนขยายที่ฉันคิดว่าใช้ในมุมมอง:

public static class DateTimeExtensions
{
    public static DateTime UtcToLocal(this DateTime source, 
        TimeZoneInfo localTimeZone)
    {
        return TimeZoneInfo.ConvertTimeFromUtc(source, localTimeZone);
    }

    public static DateTime LocalToUtc(this DateTime source, 
        TimeZoneInfo localTimeZone)
    {
        source = DateTime.SpecifyKind(source, DateTimeKind.Unspecified);
        return TimeZoneInfo.ConvertTimeToUtc(source, localTimeZone);
    }
}

ฉันคิดว่าการจัดการกับเขตเวลาจะเป็นเรื่องธรรมดาเมื่อพิจารณาจากแอปพลิเคชั่นมากมายตอนนี้ใช้ระบบคลาวด์ซึ่งเวลาท้องถิ่นของเซิร์ฟเวอร์อาจแตกต่างจากโซนเวลาที่คาดไว้มาก

สิ่งนี้ได้รับการแก้ไขอย่างงดงามมาก่อนหรือไม่? มีอะไรที่ฉันขาดหายไปไหม ความคิดและความคิดมีความชื่นชมมาก

แก้ไข:เพื่อล้างความสับสนฉันคิดว่าเพิ่มรายละเอียดเพิ่มเติม ปัญหาในตอนนี้ไม่ใช่วิธีการจัดเก็บเวลา UTC ในฐานข้อมูล แต่เป็นข้อมูลเพิ่มเติมเกี่ยวกับกระบวนการดำเนินการจาก UTC-> ท้องถิ่นและท้องถิ่น -> UTC @Max Zerbini ชี้ว่าเห็นได้ชัดว่ามันฉลาดที่จะใส่ UTC-> Local code ในมุมมอง แต่ใช้DateTimeExtensionsคำตอบจริงหรือไม่ เมื่อรับข้อมูลจากผู้ใช้การรับวันที่เป็นเวลาท้องถิ่นของผู้ใช้ (เนื่องจากเป็นสิ่งที่ JS จะใช้) จากนั้นใช้ a ModelBinderเพื่อแปลงเป็น UTC หรือไม่ เขตเวลาของผู้ใช้จะถูกเก็บไว้ในฐานข้อมูลและดึงข้อมูลได้ง่าย


3
แรกที่คุณอาจจะมีการอ่านผ่านการโพสต์ที่ยอดเยี่ยมนี้ ... ปรับเวลาตามฤดูกาลและเขตเวลาปฏิบัติที่ดีที่สุด
dodgy_coder

@dodgy_coder - มันเป็นลิงก์ที่ยอดเยี่ยมสำหรับเขตเวลา อย่างไรก็ตามมันไม่ได้แก้ปัญหาใด ๆ ของฉัน (เฉพาะที่เกี่ยวข้องกับ MVC) ขอบคุณแม้ว่า
TheCloudlessSky

code.google.com/p/noda-timeอาจเป็นประโยชน์
Arnis Lapsa

อยากรู้วิธีแก้ปัญหาที่คุณเลือกใช้ เผชิญการตัดสินใจที่คล้ายกันตัวเอง คำถามที่ดี.
ฌอน

@Sean - การแก้ปัญหายังไม่ได้สง่างาม (ซึ่งเป็นเหตุผลที่ฉันยังไม่ได้รับคำตอบ) มันเป็นค่าใช้จ่ายจำนวนมากด้วยตนเองในการพิมพ์วันที่ / เวลาและทำการแปลงกลับด้วยModelBinderตนเอง
TheCloudlessSky

คำตอบ:


106

ไม่ใช่ว่านี่คือคำแนะนำ แต่เป็นการแบ่งปันกระบวนทัศน์มากขึ้น แต่เป็นวิธีที่ก้าวร้าวที่สุดที่ฉันเคยเห็นในการจัดการข้อมูลเขตเวลาในเว็บแอป (ซึ่งไม่รวมถึง ASP.NET MVC) มีดังต่อไปนี้:

  • เวลาวันที่ทั้งหมดบนเซิร์ฟเวอร์คือ UTC DateTime.UtcNowนั่นหมายถึงการใช้เช่นคุณกล่าวว่า

  • พยายามที่จะเชื่อถือลูกค้าผ่านวันที่ไปยังเซิร์ฟเวอร์น้อยที่สุด ตัวอย่างเช่นหากคุณต้องการ "ตอนนี้" อย่าสร้างวันที่บนไคลเอนต์แล้วส่งต่อไปยังเซิร์ฟเวอร์ สร้างวันที่ในการ GET และผ่านมันไป ViewModel หรือ POST DateTime.UtcNowไม่

จนถึงตอนนี้ค่าโดยสารมาตรฐานค่อนข้างดี แต่นี่คือสิ่งที่ 'น่าสนใจ'

  • หากคุณต้องยอมรับวันที่จากไคลเอนต์ให้ใช้จาวาสคริปต์เพื่อให้แน่ใจว่าข้อมูลที่คุณโพสต์ไปยังเซิร์ฟเวอร์นั้นอยู่ใน UTC ลูกค้ารู้ว่ามันอยู่ในเขตเวลาใดดังนั้นจึงสามารถแปลงเวลาให้เป็น UTC ได้อย่างแม่นยำ

  • เมื่อแสดงมุมมองพวกเขากำลังใช้<time>องค์ประกอบHTML5 พวกเขาจะไม่แสดงชุดข้อมูลโดยตรงใน ViewModel มันถูกนำมาใช้เป็นเป็นส่วนขยายบางอย่างเช่นHtmlHelper มันจะทำให้Html.Time(Model.when)<time datetime='[utctime]' data-date-format='[datetimeformat]'></time>

    จากนั้นพวกเขาจะใช้จาวาสคริปต์เพื่อแปลเวลา UTC เป็นเวลาท้องถิ่นของลูกค้า สคริปต์จะค้นหา<time>องค์ประกอบทั้งหมดและใช้date-formatคุณสมบัติข้อมูลเพื่อจัดรูปแบบวันที่และเติมเนื้อหาขององค์ประกอบ

วิธีนี้พวกเขาไม่เคยติดตามจัดเก็บหรือจัดการเขตเวลาของลูกค้า เซิร์ฟเวอร์ไม่สนใจว่าเขตเวลาที่ไคลเอ็นต์อยู่หรือไม่ต้องทำการแปลเขตเวลาใด ๆ มันแค่คาย UTC และให้ลูกค้าแปลงสิ่งนั้นเป็นสิ่งที่สมเหตุสมผล ซึ่งเป็นเรื่องง่ายจากเบราว์เซอร์เพราะมันรู้ว่าเขตเวลามันคืออะไรถ้าลูกค้าเปลี่ยน / เขตเวลาของเขา / เธอเว็บแอปพลิเคชันจะปรับปรุงตัวเองโดยอัตโนมัติ สิ่งเดียวที่เก็บไว้คือสตริงรูปแบบวันที่และเวลาสำหรับสถานที่ของผู้ใช้

ฉันไม่ได้บอกว่ามันเป็นวิธีการที่ดีที่สุด แต่มันก็เป็นวิธีที่แตกต่างที่ฉันไม่เคยเห็นมาก่อน บางทีคุณอาจรวบรวมแนวคิดที่น่าสนใจจากมัน


ขอบคุณสำหรับคำตอบของคุณ เมื่อรับอินพุตวันที่จากผู้ใช้ (เช่นกำหนดเวลาการนัดหมาย) อินพุตนี้จะไม่ถือว่าอยู่ในเขตเวลาปัจจุบันหรือไม่ คุณคิดอย่างไรกับ ModelBinder ที่ทำการเปลี่ยนแปลงนี้ก่อนที่จะเข้าสู่การกระทำ (ดูความคิดเห็นของฉันที่ @casperOne นอกจากนี้<time>แนวคิดยังเจ๋งมากข้อเสียเพียงอย่างเดียวคือมันหมายความว่าฉันต้องค้นหา DOM ทั้งหมดสำหรับองค์ประกอบเหล่านี้ ไม่ดีเพียงแปลงวันที่ (สิ่งที่เกี่ยวกับ JS ปิดการใช้งาน?) ขอขอบคุณอีกครั้ง!
TheCloudlessSky

โดยปกติใช่สมมติฐานคือมันจะอยู่ในเขตเวลาท้องถิ่น แต่พวกเขาได้ชี้ให้เห็นว่าเมื่อใดก็ตามที่พวกเขารวบรวมเวลาจากผู้ใช้มันจะถูกแปลงเป็น UTC โดยใช้จาวาสคริปต์ก่อนที่มันจะถูกส่งไปยังเซิร์ฟเวอร์ วิธีแก้ปัญหาของพวกเขานั้นหนักมากและไม่ได้ลดลงอย่างมากเมื่อปิดตัวลง ฉันไม่ได้คิดมากพอที่จะดูว่ามีสิ่งที่ฉลาดรอบ ๆ แต่อย่างที่ฉันพูดบางทีมันอาจจะทำให้คุณมีความคิด
J. Holmes

2
ตั้งแต่ฉันทำงานในโครงการอื่นที่ต้องการวันที่ในท้องถิ่นและนี่คือวิธีการที่ฉันใช้ ฉันใช้moment.jsเพื่อทำการจัดรูปแบบวันที่ / เวลา ... มันน่ารัก ขอบคุณ!
TheCloudlessSky

ไม่มีวิธีง่ายๆในการกำหนดใน app.config / web.cofig ของแอปพลิเคชันเป็นเขตเวลาของขอบเขตแอปพลิเคชันและทำให้เปลี่ยนค่า DateTime.Now ทั้งหมดเป็น DateTime.UtcNow หรือไม่ (ฉันต้องการหลีกเลี่ยงสถานการณ์ที่โปรแกรมเมอร์ใน บริษัท จะยังคงใช้ DateTime.Now โดยไม่ได้ตั้งใจ)
ยูริ Abramson

3
ข้อเสียอย่างหนึ่งของแนวทางนี้ที่ฉันเห็นคือเมื่อคุณใช้เวลากับสิ่งอื่นการสร้างไฟล์ PDF อีเมลและอื่น ๆ ไม่มีองค์ประกอบเวลาสำหรับสิ่งเหล่านั้นดังนั้นคุณจะต้องแปลงด้วยตนเอง มิฉะนั้นวิธีการแก้ปัญหาที่เป็นระเบียบมาก
shenku

15

หลังจากการตอบรับหลายครั้งนี่เป็นคำตอบสุดท้ายของฉันซึ่งฉันคิดว่าสะอาดและเรียบง่ายและครอบคลุมประเด็นการประหยัดเวลากลางวัน

1 - เราจัดการการแปลงที่ระดับรูปแบบ ดังนั้นในคลาส Model เราเขียน:

    public class Quote
    {
        ...
        public DateTime DateCreated
        {
            get { return CRM.Global.ToLocalTime(_DateCreated); }
            set { _DateCreated = value.ToUniversalTime(); }
        }
        private DateTime _DateCreated { get; set; }
        ...
    }

2 - ในผู้ช่วยทั่วโลกเราสร้างฟังก์ชั่นที่กำหนดเองของเรา "ToLocalTime":

    public static DateTime ToLocalTime(DateTime utcDate)
    {
        var localTimeZoneId = "China Standard Time";
        var localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(localTimeZoneId);
        var localTime = TimeZoneInfo.ConvertTimeFromUtc(utcDate, localTimeZone);
        return localTime;
    }

3 - เราสามารถปรับปรุงเพิ่มเติมนี้ได้โดยการบันทึกรหัสเขตเวลาในแต่ละโปรไฟล์ผู้ใช้เพื่อให้เราสามารถดึงข้อมูลจากระดับผู้ใช้แทนการใช้ "จีนเวลามาตรฐาน" คงที่:

public class Contact
{
    ...
    public string TimeZone { get; set; }
    ...
}

4 - ที่นี่เราสามารถรับรายการของเขตเวลาที่จะแสดงต่อผู้ใช้เพื่อเลือกจากดรอปดาวน์บ็อกซ์:

public class ListHelper
{
    public IEnumerable<SelectListItem> GetTimeZoneList()
    {
        var list = from tz in TimeZoneInfo.GetSystemTimeZones()
                   select new SelectListItem { Value = tz.Id, Text = tz.DisplayName };

        return list;
    }
}

ดังนั้นตอนนี้เวลา 9:25 น. ในประเทศจีนเว็บไซต์โฮสต์ในสหรัฐอเมริกาวันที่บันทึกใน UTC ที่ฐานข้อมูลนี่คือผลลัพธ์สุดท้าย:

5/9/2013 6:25:58 PM (Server - in USA) 
5/10/2013 1:25:58 AM (Database - Converted UTC)
5/10/2013 9:25:58 AM (Local - in China)

แก้ไข

ขอขอบคุณแมตต์จอห์นสันที่ชี้ให้เห็นถึงส่วนที่อ่อนแอของโซลูชันดั้งเดิมและขออภัยที่ลบโพสต์ต้นฉบับ แต่มีปัญหาในการรับรูปแบบการแสดงรหัสที่ถูกต้อง ... กลายเป็นบรรณาธิการมีปัญหาในการผสม "กระสุน" กับ "รหัสล่วงหน้า" ดังนั้น ลบวัวและมันก็โอเค


ดูเหมือนว่าจะใช้งานได้หากบางคนไม่มีสถาปัตยกรรมระดับ n หรือเว็บไลบรารีร่วมกัน วิธีที่เราสามารถแชร์รหัสเขตเวลากับชั้นข้อมูล
Vikash Kumar

9

ในส่วนเหตุการณ์ในsf4answersผู้ใช้ป้อนที่อยู่สำหรับเหตุการณ์เช่นเดียวกับวันที่เริ่มต้นและวันที่สิ้นสุดที่ไม่จำเป็น เวลาเหล่านี้ถูกแปลเป็นdatetimeoffsetเซิร์ฟเวอร์ SQL ที่บัญชีสำหรับการชดเชยจาก UTC

นี่เป็นปัญหาเดียวกับที่คุณกำลังเผชิญ (แม้ว่าคุณกำลังใช้วิธีการที่แตกต่างกันในการที่คุณกำลังใช้DateTime.UtcNow); คุณมีที่ตั้งและคุณต้องแปลเวลาจากเขตเวลาหนึ่งเป็นอีกโซนหนึ่ง

มีสองสิ่งหลักที่ฉันทำซึ่งทำงานให้ฉัน ขั้นแรกให้ใช้DateTimeOffsetโครงสร้างเสมอ มันบัญชีเพื่อชดเชยจาก UTC และถ้าคุณสามารถรับข้อมูลจากลูกค้าของคุณมันทำให้ชีวิตของคุณง่ายขึ้นเล็กน้อย

ประการที่สองเมื่อดำเนินการแปลโดยสมมติว่าคุณทราบตำแหน่ง / โซนเวลาที่ไคลเอ็นต์อยู่คุณสามารถใช้ฐานข้อมูลเขตเวลาสาธารณะเพื่อแปลเวลาจาก UTC ไปยังโซนเวลาอื่น (หรือกำหนดตำแหน่งถ้าคุณต้องการระหว่างสอง โซนเวลา). สิ่งที่ยอดเยี่ยมเกี่ยวกับฐานข้อมูล tz (บางครั้งเรียกว่าฐานข้อมูล Olson ) คือการเปลี่ยนแปลงในเขตเวลาตลอดประวัติศาสตร์ การรับค่าชดเชยเป็นฟังก์ชั่นของวันที่ที่คุณต้องการรับค่าชดเชย (เพียงดูพระราชบัญญัตินโยบายพลังงานปี 2548ซึ่งเปลี่ยนวันที่เมื่อเวลาออมแสงตามฤดูกาลมีผลบังคับใช้ในสหรัฐอเมริกา )

กับฐานข้อมูลในมือคุณสามารถใช้zoneinfo (TZ ฐานข้อมูลฐานข้อมูล / โอลสัน) .NET API โปรดทราบว่าไม่มีการกระจายแบบไบนารีคุณจะต้องดาวน์โหลดเวอร์ชันล่าสุดและรวบรวมด้วยตัวคุณเอง

ในขณะที่เขียนนี้ในขณะนี้จะแยกวิเคราะห์ไฟล์ทั้งหมดในการกระจายข้อมูลล่าสุด (จริง ๆ แล้วฉันวิ่งข้ามไฟล์ftp://elsie.nci.nih.gov/pub/tzdata2011k.tar.gzในวันที่ 25 กันยายน 2011; ในเดือนมีนาคม 2560 คุณจะได้รับผ่านhttps://iana.org/time-zonesหรือจากftp://fpt.iana.org/tz/releases/tzdata2017a.tar.gz )

ดังนั้นใน sf4answers หลังจากได้รับที่อยู่มันถูกระบุพิกัดทางภูมิศาสตร์เป็นชุดละติจูด / ลองจิจูดแล้วส่งไปยังบริการเว็บของบุคคลที่สามเพื่อรับเขตเวลาที่สอดคล้องกับรายการในฐานข้อมูล tz จากจุดนั้นเวลาเริ่มต้นและสิ้นสุดจะถูกแปลงเป็นDateTimeOffsetอินสแตนซ์ที่มีออฟเซ็ต UTC ที่เหมาะสมแล้วจัดเก็บในฐานข้อมูล

สำหรับการจัดการกับ SO และเว็บไซต์ขึ้นอยู่กับผู้ชมและสิ่งที่คุณพยายามแสดง หากคุณสังเกตเห็นเว็บไซต์โซเชียลส่วนใหญ่ (และ SO และส่วนเหตุการณ์บน sf4answers) จะแสดงเหตุการณ์ในเวลาที่สัมพันธ์กันหรือหากใช้ค่าสัมบูรณ์ก็มักจะเป็น UTC

อย่างไรก็ตามหากผู้ชมของคุณคาดว่าเวลาท้องถิ่นจากนั้นใช้DateTimeOffsetพร้อมกับวิธีการขยายที่ใช้เวลาในการแปลงเป็นจะดี ชนิดข้อมูล SQL datetimeoffsetจะแปลเป็น. NET DateTimeOffsetซึ่งคุณจะได้รับเวลาสากลสำหรับการใช้GetUniversalTimeวิธีนี้ จากตรงนั้นคุณเพียงแค่ใช้วิธีการในZoneInfoชั้นเรียนเพื่อแปลงจาก UTC เป็นเวลาท้องถิ่น (คุณจะต้องทำงานเล็กน้อยเพื่อให้มันเป็น a DateTimeOffsetแต่มันง่ายพอที่จะทำ)

จะทำการแปลงที่ไหน นั่นเป็นค่าใช้จ่ายที่คุณจะต้องจ่ายที่ไหนสักแห่งและไม่มีวิธีที่ "ดีที่สุด" ฉันเลือกใช้มุมมองด้วยการตั้งค่าเขตเวลาเป็นส่วนหนึ่งของโมเดลมุมมองที่แสดงต่อมุมมอง ด้วยวิธีนี้หากข้อกำหนดสำหรับการเปลี่ยนแปลงมุมมองคุณไม่จำเป็นต้องเปลี่ยนโมเดลมุมมองของคุณเพื่อรองรับการเปลี่ยนแปลง คุณJsonResultเพียงแค่จะมีรูปแบบที่มีและชดเชยIEnumerable<T>

ที่ด้านอินพุทการใช้เครื่องผูกรุ่น? ฉันจะบอกว่าไม่มีทาง คุณไม่สามารถรับประกันได้ว่าวันที่ทั้งหมด (ตอนนี้หรือในอนาคต) จะต้องมีการแปลงในลักษณะนี้มันควรจะเป็นฟังก์ชั่นที่ชัดเจนของตัวควบคุมของคุณเพื่อดำเนินการนี้ หากข้อกำหนดเปลี่ยนไปคุณไม่จำเป็นต้องปรับแต่งหนึ่งหรือหลายModelBinderอินสแตนซ์เพื่อปรับตรรกะทางธุรกิจของคุณ และเป็นตรรกะทางธุรกิจซึ่งหมายความว่ามันควรจะอยู่ในตัวควบคุม


ขอขอบคุณสำหรับการตอบกลับอย่างละเอียด ฉันหวังว่าฉันจะไม่เจอเรื่องหยาบคาย แต่สิ่งนี้ไม่ได้ตอบข้อกังวลใด ๆ ของฉันกับ ASP.NET MVC: สิ่งที่เกี่ยวกับการป้อนข้อมูลของผู้ใช้ และที่สำคัญที่สุดแล้วการแสดงวันที่เหล่านี้ (ในเขตเวลาท้องถิ่นของผู้ใช้) คืออะไร ฉันรู้สึกว่าวิธีการขยายจะเพิ่มน้ำหนักจำนวนมากให้กับมุมมองของฉันที่ดูเหมือนไม่จำเป็น
TheCloudlessSky

1
@TheCloudlessSky: ดูสองย่อหน้าสุดท้ายของการตอบกลับที่แก้ไขของฉัน โดยส่วนตัวแล้วฉันคิดว่ารายละเอียดของการเปลี่ยนแปลงที่น้อย ปัญหาสำคัญคือการแปลงจริงและการจัดเก็บข้อมูลวันที่และเวลา (btw ฉันไม่สามารถเน้นการใช้งานdatetimeoffsetใน SQL Server และDateTimeOffsetใน. NET ที่นี่พวกเขาลดความซับซ้อนของสิ่งต่าง ๆ อย่างมาก) ซึ่งฉันเชื่อว่า. NET ไม่ได้จัดการอย่างเพียงพอ เลยด้วยเหตุผลที่ระบุไว้ข้างต้น หากคุณมีวันที่ใน NYC ที่ป้อนในปี 2003 และจากนั้นคุณต้องการให้มันแปลเป็นวันที่ใน LA ในปี 2011, .NET ล้มเหลวอย่างหนักในกรณีนี้
casperOne

ปัญหาที่ไม่ได้ใช้ตัวประสานโมเดล (หรือเลเยอร์ใด ๆ ก่อนการกระทำ) คือตัวควบคุมทุกตัวนั้นยากที่จะทดสอบเมื่อทำงานกับวันที่ (พวกเขาต้องการการพึ่งพาการแปลงวันที่) สิ่งนี้จะทำให้สามารถเขียนวันที่ทดสอบหน่วยใน UTC ได้ แอปพลิเคชันของฉันมีผู้ใช้ที่เกี่ยวข้องกับโปรไฟล์ (คิดว่าหมอ / เลขานุการที่เกี่ยวข้องกับการปฏิบัติของพวกเขา) โปรไฟล์เก็บข้อมูลเขตเวลา ดังนั้นจึงเป็นเรื่องง่ายที่จะรับเขตเวลาของโปรไฟล์ผู้ใช้ปัจจุบันและแปลงระหว่างการผูก คุณมีข้อโต้แย้งอื่น ๆ ในเรื่องนี้หรือไม่? ขอบคุณสำหรับข้อมูลของคุณ!
TheCloudlessSky

กรณีที่เป็นที่การทดสอบของคุณจะไม่ถูกต้องสะท้อนให้เห็นถึงกรณีทดสอบ การป้อนข้อมูลของคุณจะไม่อยู่ใน UTC ดังนั้นกรณีทดสอบของคุณไม่ควรถูกสร้างขึ้นเพื่อใช้งาน ควรใช้วันที่ในโลกแห่งความเป็นจริงกับสถานที่และทุกอย่าง (แม้ว่าคุณจะใช้งานDateTimeOffsetคุณจะลดลงได้อย่างมาก IMO)
casperOne

ใช่ - แต่นี่หมายความว่าการทดสอบทุกอย่างที่เกี่ยวข้องกับวันที่จะต้องพิจารณาเรื่องนี้ ทุกการกระทำที่เกี่ยวข้องกับชุดข้อมูลจะแปลงเป็น UTC เสมอ ให้ฉันนี้เป็นตัวเต็งสำหรับรูปแบบเครื่องผูกแล้วทดสอบสารยึดเกาะแบบ
TheCloudlessSky

5

นี่เป็นเพียงความคิดเห็นของฉันฉันคิดว่าแอปพลิเคชัน MVC ควรแยกปัญหาการนำเสนอข้อมูลที่ดีจากการจัดการแบบจำลองข้อมูล ฐานข้อมูลสามารถเก็บข้อมูลในเวลาเซิร์ฟเวอร์ท้องถิ่น แต่เป็นหน้าที่ของเลเยอร์การนำเสนอเพื่อแสดงวันที่และเวลาโดยใช้เขตเวลาของผู้ใช้ท้องถิ่น นี่ดูเหมือนว่าฉันจะเป็นปัญหาเดียวกับ I18N และรูปแบบตัวเลขสำหรับประเทศต่างๆ ในกรณีของคุณแอปพลิเคชันของคุณควรตรวจจับCultureและเขตเวลาของผู้ใช้และเปลี่ยนมุมมองที่แสดงข้อความตัวเลขและการนำเสนอข้อมูลที่แตกต่างกัน แต่ข้อมูลที่เก็บไว้สามารถมีรูปแบบเดียวกันได้


ขอบคุณสำหรับคำตอบของคุณ ใช่นี่คือสิ่งที่ฉันอธิบายโดยทั่วไปฉันแค่สงสัยว่าสิ่งนี้จะประสบความสำเร็จอย่างงดงามด้วย MVC แอพจัดเก็บเขตเวลาของผู้ใช้เป็นส่วนหนึ่งของการสร้างบัญชีของพวกเขา (พวกเขาเลือกเขตเวลา) ปัญหาอีกครั้งมาพร้อมกับวิธีการแสดงวันที่ในแต่ละมุมมองโดยไม่ต้อง (หวังว่า) จะต้องทิ้งขยะด้วยวิธีการที่ฉันสร้างขึ้นDateTimeExtensionsมา
TheCloudlessSky

มีหลายวิธีในการทำเช่นนี้วิธีหนึ่งคือใช้วิธีการช่วยเหลือตามที่คุณแนะนำวิธีอื่นอาจซับซ้อนกว่า แต่สวยงามคือการใช้ตัวกรองที่ประมวลผลคำขอและการตอบสนองและแปลงวันที่และเวลา อีกวิธีหนึ่งคือการพัฒนาแอตทริบิวต์การแสดงผลที่กำหนดเองเพื่อใส่คำอธิบายประกอบฟิลด์ประเภท DateTime ของมุมมองแบบจำลองของคุณ
Massimo Zerbini

นี่คือสิ่งที่ฉันกำลังมองหา หากคุณดู OP ของฉันฉันยังกล่าวถึงการใช้ AutoMapper เพื่อทำการประมวลผลก่อนที่จะไปดูผลลัพธ์ / json แต่หลังจากการดำเนินการได้ดำเนินการ
TheCloudlessSky

1

สำหรับเอาต์พุตให้สร้างเทมเพลตการแสดงผล / ตัวแก้ไขเช่นนี้

@inherits System.Web.Mvc.WebViewPage<System.DateTime>
@Html.Label(Model.ToLocalTime().ToLongTimeString()))

คุณสามารถผูกมันตามคุณสมบัติในแบบจำลองของคุณหากคุณต้องการให้บางรุ่นใช้แม่แบบเหล่านั้น

ดูที่นี่และที่นี่สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการสร้างเทมเพลตแก้ไขที่กำหนดเอง

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

ลิงค์นี้จะช่วยผลักคุณไปในทิศทางที่ถูกต้องหากคุณต้องการลงบนเส้นทางนั้น

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


ฉันคิดว่าเทมเพลตและตัวแก้ไขการแสดงผลที่กำหนดเองและตัวยึดประสานเป็นโซลูชันที่หรูหราที่สุดเพราะมันจะ "ใช้งานได้" เมื่อนำไปใช้งานแล้ว ผู้พัฒนาไม่จำเป็นต้องรู้อะไรเป็นพิเศษเพื่อให้วันที่ใช้งานถูกต้องDisplayForและใช้EditorForงานได้ทุกครั้ง +1
Kevin Stricker

17
สิ่งนี้จะไม่แสดงเวลาของเซิร์ฟเวอร์แอปพลิเคชันและไม่ใช่เวลาของเบราว์เซอร์หรือไม่
อเล็กซ์

0

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

ฉันคิดว่าสิ่งนี้สามารถทำได้โดยใช้ PostSharp หรือผกผันของคอนเทนเนอร์ควบคุม

โดยส่วนตัวแล้วฉันจะแปลงชุดข้อมูลของคุณใน UI อย่างชัดเจน ...

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