डेटाइम ऑब्जेक्ट्स को गोल करना


105

मैं चार्टिंग एप्लिकेशन के लिए निकटतम अंतराल के लिए तारीखों / समय को गोल करना चाहता हूं। मैं एक विस्तार विधि हस्ताक्षर पसंद करता हूं, ताकि किसी भी स्तर की सटीकता के लिए गोलाई को ठीक किया जा सके:

static DateTime Round(this DateTime date, TimeSpan span);

विचार यह है कि अगर मैं दस मिनट के समय में गुजरता हूं, तो यह निकटतम दस मिनट के अंतराल पर पहुंच जाएगा। मैं कार्यान्वयन के आसपास अपना सिर नहीं पा सकता हूं और उम्मीद कर रहा हूं कि आप में से किसी ने पहले भी ऐसा ही लिखा होगा या इस्तेमाल किया होगा।

मुझे लगता है कि या तो एक मंजिल, छत या निकटतम कार्यान्वयन ठीक है।

कोई विचार?

संपादित करें: @tvanfosson & @ShuggyCoUk के लिए धन्यवाद, कार्यान्वयन इस तरह दिखता है:

public static class DateExtensions {
    public static DateTime Round(this DateTime date, TimeSpan span) {
        long ticks = (date.Ticks + (span.Ticks / 2) + 1)/ span.Ticks;
        return new DateTime(ticks * span.Ticks);
    }
    public static DateTime Floor(this DateTime date, TimeSpan span) {
        long ticks = (date.Ticks / span.Ticks);
        return new DateTime(ticks * span.Ticks);
    }
    public static DateTime Ceil(this DateTime date, TimeSpan span) {
        long ticks = (date.Ticks + span.Ticks - 1) / span.Ticks;
        return new DateTime(ticks * span.Ticks);
    }
}

और ऐसा कहा जाता है:

DateTime nearestHour = DateTime.Now.Round(new TimeSpan(1,0,0));
DateTime minuteCeiling = DateTime.Now.Ceil(new TimeSpan(0,1,0));
DateTime weekFloor = DateTime.Now.Floor(new TimeSpan(7,0,0,0));
...

चीयर्स!


1
यहाँ कुछ कार्यान्वयन भी मदद कर सकते हैं: stackoverflow.com/questions/766626/…
मैट हैमिल्टन


3
नया बनाया गया दिनांक पूर्व में मूल DateTimeKind जोड़ना न भूलें: नया DateTime (ticks * span.Ticks, date.Kind);
AM

जवाबों:


130

मंज़िल

long ticks = date.Ticks / span.Ticks;

return new DateTime( ticks * span.Ticks );

गोल (मिडपॉइंट पर)

long ticks = (date.Ticks + (span.Ticks / 2) + 1)/ span.Ticks;

return new DateTime( ticks * span.Ticks );

अधिकतम सीमा

long ticks = (date.Ticks + span.Ticks - 1)/ span.Ticks;

return new DateTime( ticks * span.Ticks );

5
मैं हाल ही में एक मुद्दे पर भाग गया, जहाँ DateTimeKind संरक्षित नहीं था। प्रत्येक विधि में अंतिम पंक्ति के लिए निम्नलिखित ट्वीक ने मेरे मामले में मदद की:return new DateTime(ticks * span.Ticks, date.Kind);
Peet

39

यह आपको दिए गए किसी भी अंतराल के लिए गोल कर देगा। यह विभाजित करने और फिर टिक्स को गुणा करने की तुलना में थोड़ा तेज है।

public static class DateTimeExtensions
{
  public static DateTime Floor(this DateTime dateTime, TimeSpan interval)
  {
    return dateTime.AddTicks(-(dateTime.Ticks % interval.Ticks));
  }

  public static DateTime Ceiling(this DateTime dateTime, TimeSpan interval)
  {
    var overflow = dateTime.Ticks % interval.Ticks;

    return overflow == 0 ? dateTime : dateTime.AddTicks(interval.Ticks - overflow);
  }

  public static DateTime Round(this DateTime dateTime, TimeSpan interval)
  {
    var halfIntervalTicks = (interval.Ticks + 1) >> 1;

    return dateTime.AddTicks(halfIntervalTicks - ((dateTime.Ticks + halfIntervalTicks) % interval.Ticks));
  }
}

11

यदि आप अपनी गोलाई चाहते हैं तो आपको यह भी स्पष्ट होना चाहिए:

  1. अंतराल के प्रारंभ, अंत या मध्य में होना
    • शुरुआत सबसे आसान और अक्सर अपेक्षित है लेकिन आपको अपने शुरुआती अनुमान में स्पष्ट होना चाहिए।
  2. आप किस तरह से सीमा मामलों को गोल करना चाहते हैं।
    • आम तौर पर केवल एक मुद्दा है अगर आप अंत के बजाय मध्य की ओर बढ़ रहे हैं।
    • चूंकि बीच में गोलाई एक पूर्वाग्रह मुक्त उत्तर पर एक प्रयास है, इसलिए आपको बैंकरों की तरह कुछ का उपयोग करने की आवश्यकता है तकनीकी रूप से गोल आधा गोल करना भी वास्तव में पूर्वाग्रह से मुक्त होना है।

यह काफी संभावना है कि आप वास्तव में केवल पहले बिंदु के बारे में परवाह करते हैं, लेकिन इन 'सरल' प्रश्नों में परिणामी व्यवहार के बहुत दूरगामी परिणाम हो सकते हैं क्योंकि आप इसे वास्तविक दुनिया में उपयोग करते हैं (अक्सर शून्य से सटे अंतराल पर)

tvanfosson के सॉल्यूशन के कवर सभी मामलों में सूचीबद्ध हैं। मिडपॉइंट उदाहरण ऊपर की ओर पक्षपाती है। यह संदेह है कि यह समय से संबंधित गोलाई में एक समस्या होगी।


3

बस टिक्स का उपयोग करें, जिसका उपयोग मान को विभाजित करने, फर्श / छत / गोल करने के लिए और इसे वापस गुणा करें।


-2

अगर आप सिर्फ ऑवर टू सीलिंग वैल्यू राउंड अप करना चाहते हैं

Console.WriteLine(DateTime.Now.ToString("M/d/yyyy hh:00:00"));

ओपी ने रिटर्निंग ऑब्जेक्ट के रूप में डेटटाइम का अनुरोध किया।
a.t.toulan
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.