.NET डेटाइम से मिलीसेकंड को कैसे छोटा करें


334

मैं एक आने वाले अनुरोध से एक टाइम स्टैम्प की तुलना डेटाबेस संग्रहित मूल्य से करने का प्रयास कर रहा हूं। SQL सर्वर निश्चित रूप से समय पर मिलीसेकंड की कुछ सटीकता रखता है, और जब .NET डेटटाइम में पढ़ा जाता है, तो इसमें उन मिलीसेकंड शामिल होते हैं। सिस्टम के लिए आने वाला अनुरोध, हालांकि, उस सटीकता की पेशकश नहीं करता है, इसलिए मुझे बस मिलीसेकंड ड्रॉप करने की आवश्यकता है।

मुझे लगता है कि मुझे कुछ स्पष्ट याद आ रहा है, लेकिन मुझे इसे करने का एक सुंदर तरीका नहीं मिला है (C #)।


(तीसरा प्रयास ...) चूंकि 20% उत्तर ( 1 , 2 , 3 ) वर्णन करते हैं कि कैसे stringएक के स्वरूपित प्रतिनिधित्व से मिलीसेकंड घटक को छोड़ना या निकालना है DateTime, शायद यह स्पष्ट करने के लिए एक संपादन की आवश्यकता है कि "छोटा करें" / "ड्रॉप" मिलीसेकेंड का अर्थ है "एक उत्पादन DateTimeमूल्य, जहां सभी दिनांक / समय घटकों को छोड़कर एक ही हैं TimeOfDay.TotalMillisecondsहै 0।" लोग, बिल्कुल नहीं पढ़ते हैं, लेकिन किसी भी अस्पष्टता को खत्म करने के लिए।
BACON

जवाबों:


556

निम्नांकित अंशकालिक के लिए काम करेगा जिसमें अंशों का अंश है, और यह तरह की संपत्ति (स्थानीय, यूटीसी या अपरिभाषित) को भी संरक्षित करता है।

DateTime dateTime = ... anything ...
dateTime = new DateTime(
    dateTime.Ticks - (dateTime.Ticks % TimeSpan.TicksPerSecond), 
    dateTime.Kind
    );

या समकक्ष और छोटा:

dateTime = dateTime.AddTicks( - (dateTime.Ticks % TimeSpan.TicksPerSecond));

इसे विस्तार विधि में सामान्यीकृत किया जा सकता है:

public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan)
{
    if (timeSpan == TimeSpan.Zero) return dateTime; // Or could throw an ArgumentException
    if (dateTime == DateTime.MinValue || dateTime == DateTime.MaxValue) return dateTime; // do not modify "guard" values
    return dateTime.AddTicks(-(dateTime.Ticks % timeSpan.Ticks));
}

जो निम्नानुसार उपयोग किया जाता है:

dateTime = dateTime.Truncate(TimeSpan.FromMilliseconds(1)); // Truncate to whole ms
dateTime = dateTime.Truncate(TimeSpan.FromSeconds(1)); // Truncate to whole second
dateTime = dateTime.Truncate(TimeSpan.FromMinutes(1)); // Truncate to whole minute
...

जब मैं आपको यह दे दूँगा क्योंकि आप तकनीकी रूप से सही हैं, तो कुछ वितरित डेटा (मेरे मामले में एक वेब-आधारित अनुरोध) की तुलना करने के लिए SQL सर्वर से डेटा पढ़ने वाले लोगों के लिए, यह संकल्प की राशि आवश्यक नहीं है।
जेफ पुटज

1
अच्छा लगा। स्पष्ट रूप से किसी को डेटटाइम क्लास को कुछ विस्तार विधियों को निकटतम करने के लिए देने की आवश्यकता है, ताकि इस प्रकार के अच्छे कोडिंग का पुन: उपयोग हो।
chris.w.mclean

यह बहुत संभावना नहीं है, लेकिन जब टिक = 0 होता है तो क्या यह दृष्टिकोण नहीं टूटता है?
24'13 को

@adotout, ऊपर दी गई ट्रुनेट विधि एक DivideByZeroException को फेंक देगी यदि टाइमस्पैन पैरामीटर शून्य है, तो क्या इसका मतलब है "टिक्स = 0" के दौरान "एप्रोच ब्रेक" से क्या मतलब है? टाइमस्पैन शून्य होने पर एक ArgumentException को फेंकना बेहतर होगा।
जो

145
var date = DateTime.Now;

date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);

34
स्पष्ट और सरल, बस यह सुनिश्चित करने के लिए कि आपको जानकारी का एक महत्वपूर्ण टुकड़ा खोना नहीं है, निर्माणकर्ता के अंत में ", date.Kind" जोड़ना याद रखें।
15

9
प्रदर्शन संवेदनशील कोड में इस समाधान के बारे में सतर्क रहें। मेरा ऐप System.DateTime.GetDatePart में CPU समय का 12% खर्च कर रहा था ।
कर्नल पैनिक

3
यह सरल है, लेकिन सबसे अच्छे उत्तर के रूप में चिह्नित प्रश्न की तुलना में धीमा है। ऐसा नहीं है कि यह एक अड़चन हो सकती है, लेकिन यह लगभग 7-8x धीमी है।
जोनास

"बहुत धीमे" कथन अतिश्योक्तिपूर्ण नहीं हैं, अंतर 50% और रनटाइम के आधार पर लगभग 100% है; शुद्ध 4.7.2: 0.35 vs बनाम 0.62 core और कोर 3.1: 0.18 0.s बनाम 0.12 10s जो माइक्रो-सेकंड (10 ^ -6 सेकंड)
जुवेन्स

61

यहाँ एक विस्तार विधि है जो पिछले उत्तर पर आधारित है जो आपको किसी भी रिज़ॉल्यूशन को कम कर देगा ...

उपयोग:

DateTime myDateSansMilliseconds = myDate.Truncate(TimeSpan.TicksPerSecond);
DateTime myDateSansSeconds = myDate.Truncate(TimeSpan.TicksPerMinute)

वर्ग:

public static class DateTimeUtils
{
    /// <summary>
    /// <para>Truncates a DateTime to a specified resolution.</para>
    /// <para>A convenient source for resolution is TimeSpan.TicksPerXXXX constants.</para>
    /// </summary>
    /// <param name="date">The DateTime object to truncate</param>
    /// <param name="resolution">e.g. to round to nearest second, TimeSpan.TicksPerSecond</param>
    /// <returns>Truncated DateTime</returns>
    public static DateTime Truncate(this DateTime date, long resolution)
    {
        return new DateTime(date.Ticks - (date.Ticks % resolution), date.Kind);
    }
}

1
यह वास्तव में लचीला और पुनः प्रयोग करने योग्य समाधान है, जो अत्यधिक क्रिया के बिना संक्षिप्त और अभिव्यंजक है। सबसे अच्छे समाधान के रूप में मेरा वोट
जासं १

2
आपको वास्तव में% ऑपरेंड के आसपास कोष्ठक की आवश्यकता नहीं है।
एरिक

8
.. लेकिन परेंस स्पष्टता जोड़ते हैं, मेरी राय में।
ओरियन एल्जेनिल

28
DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);

70
-1: केवल तभी काम करेगा जब DateTime मान में मिलीसेकंड के अंश शामिल न हों।
जो

7
इस विधि के प्रयोग से मेरी कुछ यूनिट परीक्षण विफल हो गए: उम्मीद: २०१०-०५-०५ १५: ५५: ४ ९: ०० ९ लेकिन २०१०-०५-०५ १५: ५५: ४ ९: ०४। मैं अनुमान लगा रहा हूँ कि जोई ने एक मिलीसेकंड के अंशों के बारे में क्या उल्लेख किया है।
सेठ रेनो

6
क्रमांकन के लिए काम नहीं करता है, उदाहरण के लिए 2010-12-08T11: 20: 03.000099 + 15: 00 आउटपुट है, पूरी तरह से मिलीसेकंड को काट नहीं करता है।
joedotnot

5
Millisecondसंपत्ति एक देता है पूर्णांक 0 और 999 (सम्मिलित) के बीच। इसलिए यदि ऑपरेशन से पहले दिन का समय था, तो कहें 23:48:49.1234567, तो वह पूर्णांक होगा 123, और ऑपरेशन के बाद दिन का समय होगा 23:48:49.0004567। इसलिए यह सेकंड की एक पूरी संख्या में छोटा नहीं हुआ है।
जेपी स्टिग नील्सन

11

कभी-कभी आप कुछ कैलेंडर आधारित, जैसे साल या महीने के लिए अलग करना चाहते हैं। यहां एक विस्तार विधि दी गई है जिससे आप कोई भी संकल्प चुन सकते हैं।

public enum DateTimeResolution
{
    Year, Month, Day, Hour, Minute, Second, Millisecond, Tick
}

public static DateTime Truncate(this DateTime self, DateTimeResolution resolution = DateTimeResolution.Second)
{
    switch (resolution)
    {
        case DateTimeResolution.Year:
            return new DateTime(self.Year, 1, 1, 0, 0, 0, 0, self.Kind);
        case DateTimeResolution.Month:
            return new DateTime(self.Year, self.Month, 1, 0, 0, 0, self.Kind);
        case DateTimeResolution.Day:
            return new DateTime(self.Year, self.Month, self.Day, 0, 0, 0, self.Kind);
        case DateTimeResolution.Hour:
            return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerHour));
        case DateTimeResolution.Minute:
            return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerMinute));
        case DateTimeResolution.Second:
            return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerSecond));
        case DateTimeResolution.Millisecond:
            return self.AddTicks(-(self.Ticks % TimeSpan.TicksPerMillisecond));
        case DateTimeResolution.Tick:
            return self.AddTicks(0);
        default:
            throw new ArgumentException("unrecognized resolution", "resolution");
    }
}

9

मिलीसेकंड छोड़ने के बजाय फिर तुलना करना, अंतर की तुलना क्यों नहीं की?

DateTime x; DateTime y;
bool areEqual = (x-y).TotalSeconds == 0;

या

TimeSpan precision = TimeSpan.FromSeconds(1);
bool areEqual = (x-y).Duration() < precision;

3
पहला विकल्प काम नहीं करता है, क्योंकि TotalSeconds एक डबल है; यह मिलीसेकंड भी लौटाता है।
जौइन

1
अंतर की तुलना ट्रंकिंग के समान परिणाम नहीं देता है, फिर तुलना करना। उदाहरण के लिए 5.900 और 6.100 इसके अलावा एक दूसरे से कम हैं, इसलिए आपकी विधि के बराबर तुलना करेंगे। लेकिन काटे गए मान 5 और 6 अलग हैं। जो उचित है वह आपकी आवश्यकता पर निर्भर करता है।
जो

7

कम स्पष्ट लेकिन 2 गुना से अधिक तेज:

// 10000000 runs

DateTime d = DateTime.Now;

// 484,375ms
d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);

// 1296,875ms
d = d.AddMilliseconds(-d.Millisecond);

3
ध्यान दें कि दूसरा विकल्प, d.AddMilliseconds(-d.Millisecond)जरूरी नहीं कि DateTime को पूर्व में, पूर्ण दूसरे पर ले जाए। d.Ticks % TimeSpan.TicksPerMillisecondआपके दूसरे से आगे टिक (कहीं 0 और 9,999 के बीच) रहेगा।
टेक्नेटियम

5

दूसरे दौर में उतरने के लिए:

dateTime.AddTicks(-dateTime.Ticks % TimeSpan.TicksPerSecond)

TicksPerMinuteमिनट के लिए नीचे गोल के साथ बदलें ।


यदि आपका कोड प्रदर्शन संवेदनशील है, तो सतर्क रहें

new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second)

मेरा ऐप System.DateTime.GetDatePart में CPU समय का 12% खर्च कर रहा था ।


3

आसान पढ़ने का एक तरीका है ...

//Remove milliseconds
DateTime date = DateTime.Now;
date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH:mm:ss"), "yyyy-MM-dd HH:mm:ss", null);

और अधिक...

//Remove seconds
DateTime date = DateTime.Now;
date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH:mm"), "yyyy-MM-dd HH:mm", null);

//Remove minutes
DateTime date = DateTime.Now;
date = DateTime.ParseExact(date.ToString("yyyy-MM-dd HH"), "yyyy-MM-dd HH", null);

//and go on...

4
स्ट्रिंग्स और पार्सिंग में परिवर्तित करना प्रदर्शन के मामले में एक भयानक विचार है।
जेफ पुटज

2
सच @JeffPutz, लेकिन यह है , लेकिन सरल। एक स्वचालित परीक्षण के लिए उपयुक्त जहां एक DB से डाला और खींचा गया मान टिक (मेरी सटीक स्थिति) खो देता है। हालाँकि यह उत्तर इससे भी सरल हो सकता है, क्योंकि यह var now = DateTime.Parse(DateTime.Now.ToString())ठीक काम करता है।
ग्रिम द ऑपिनर

1
@GrimmTheOpiner - "... ठीक काम करता है", ज्यादातर, लेकिन गारंटी नहीं। यह क्या करता है: "जो भी सटीक 'लंबे समय' को वर्तमान उपयोगकर्ता के नियंत्रण कक्ष की प्राथमिकताओं के रूप में कॉन्फ़िगर किया गया है, के लिए एक तिथि-निर्धारण"। जो आमतौर पर है, लेकिन जरूरी नहीं, सेकंड।
जो

1
अपनी सादगी की तरह, प्रदर्शन स्वचालित परीक्षण स्थिति के लिए एक मुद्दा नहीं है।
लियांग

1

डायडिस्टिस प्रतिक्रिया के बारे में। यह मेरे लिए काम करता है, सिवाय इसके कि मुझे गुणा से पहले विभाजन के आंशिक भाग को हटाने के लिए फर्श का उपयोग करना पड़ा। इसलिए,

d = new DateTime((d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);

हो जाता है

d = new DateTime(Math.Floor(d.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);

मुझे उम्मीद है कि दो लॉन्ग वैल्यू के विभाजन का परिणाम एक लॉन्ग में होगा, इस प्रकार दशमलव भाग को हटा दिया जाएगा, लेकिन यह गुणा के बाद सटीक मान को छोड़ते हुए इसे डबल के रूप में हल करता है।

Eppsy


1

2 ऊपर वर्णित समाधान के लिए विस्तार विधियाँ

    public static bool LiesAfterIgnoringMilliseconds(this DateTime theDate, DateTime compareDate, DateTimeKind kind)
    {
        DateTime thisDate = new DateTime(theDate.Year, theDate.Month, theDate.Day, theDate.Hour, theDate.Minute, theDate.Second, kind);
        compareDate = new DateTime(compareDate.Year, compareDate.Month, compareDate.Day, compareDate.Hour, compareDate.Minute, compareDate.Second, kind);

        return thisDate > compareDate;
    }


    public static bool LiesAfterOrEqualsIgnoringMilliseconds(this DateTime theDate, DateTime compareDate, DateTimeKind kind)
    {
        DateTime thisDate = new DateTime(theDate.Year, theDate.Month, theDate.Day, theDate.Hour, theDate.Minute, theDate.Second, kind);
        compareDate = new DateTime(compareDate.Year, compareDate.Month, compareDate.Day, compareDate.Hour, compareDate.Minute, compareDate.Second, kind);

        return thisDate >= compareDate;
    }

उपयोग:

bool liesAfter = myObject.DateProperty.LiesAfterOrEqualsIgnoringMilliseconds(startDateTime, DateTimeKind.Utc);

1

सबसे तेज़ समाधान नहीं बल्कि सरल और समझने में आसान:

DateTime d = DateTime.Now;
d = d.Date.AddHours(d.Hour).AddMinutes(d.Minute).AddSeconds(d.Second)

0
DateID.Text = DateTime.Today.ToShortDateString();

Use ToShortDateString() //Date 2-02-2016
Use ToShortDateString() // Time 

और बाय यूज

ToLongDateString() // its show 19 February 2016.

: पी


-1। मैं यह देख सकता हूं कि प्रश्न का गलत अर्थ कैसे निकाला जा सकता है क्योंकि stringइसके बजाय उत्पादन करने के लिए कहा जाता है DateTime, लेकिन यह आउटपुट से समय घटकों को पूरी तरह से छोड़ देता है । (जो Todayसंपत्ति को अनावश्यक रूप से भी एक्सेस करता है।)
BACON

0

नई विधि

String Date = DateTime.Today.ToString("dd-MMM-yyyy"); 

// स्ट्रींग पास पैरामीटर dd-mmm-yyyy वापसी 24-feb-2016

या टेक्स्टबॉक्स पर दिखाया गया है

txtDate.Text = DateTime.Today.ToString("dd-MMM-yyyy");

// पेजोनॉलाड पर डाल दिया


-1। मैं यह देख सकता हूं कि प्रश्न का गलत अर्थ कैसे निकाला जा सकता है क्योंकि stringइसके बजाय उत्पादन करने के लिए कहा जाता है DateTime, लेकिन यह आउटपुट से समय घटकों को पूरी तरह से छोड़ देता है । (जो Todayसंपत्ति को अनावश्यक रूप से भी एक्सेस करता है।)
BACON

0

मेरे मामले में, मैं सेकंड और मिलीसेकंड को सहेजे बिना डेटासटाइमपिकर टूल से टाइमस्पैन को बचाने का लक्ष्य बना रहा था, और यहां समाधान है।

सबसे पहले datetimePicker.value को अपने इच्छित प्रारूप में परिवर्तित करें, जो मेरा "HH: mm" है और फिर इसे वापस TimeSpan में परिवर्तित करें।

var datetime = datetimepicker1.Value.ToString("HH:mm");
TimeSpan timeSpan = Convert.ToDateTime(datetime).TimeOfDay;

यह करने के लिए एक बेहतर तरीका (स्पष्ट आशय, प्रारूपण और वापस पार्स करने से बचा जाता है string) ऐसा करने के लिए DateTime datetime = datetimepicker1.Value; TimeSpan timeSpan = new TimeSpan(datetime.Hour, datetime.Minute, 0); या आप जो के विस्तार की विधि के विभिन्न प्रकारों का उपयोग कर सकते हैं जोTimeSpan मूल्यों पर संचालित होते हैं और TimeSpan timeSpan = datetime.TimeOfDay.Truncate(TimeSpan.FromSeconds(1));सेकंड्स को छोटा करने के लिए उपयोग करते हैं ।
बैकोन

0

यह यहाँ और इसी तरह के प्रश्नों में पोस्ट की गई विस्तार विधियों का मेरा संस्करण है। यह आसान तरीके से पढ़ने के लिए टिक्स के मूल्य को मान्य करता है और मूल DateTime उदाहरण के DateTimeKind को संरक्षित करता है। (यह MongoDB जैसे डेटाबेस में संग्रहीत करते समय सूक्ष्म लेकिन प्रासंगिक दुष्प्रभाव होते हैं।)

यदि सही लक्ष्य एक निर्धारित समय (यानी घंटे / मिनट / सेकंड / एमएस) के लिए डेटाइम को छोटा करना है, तो मैं आपके कोड में इस एक्सटेंशन विधि को लागू करने की सलाह देता हूं। यह सुनिश्चित करता है कि आप केवल एक वैध परिशुद्धता के लिए अलग कर सकते हैं और यह आपके मूल विवरण के महत्वपूर्ण DateTimeKind मेटाडेटा को संरक्षित करता है:

public static DateTime Truncate(this DateTime dateTime, long ticks)
{
    bool isValid = ticks == TimeSpan.TicksPerDay 
        || ticks == TimeSpan.TicksPerHour 
        || ticks == TimeSpan.TicksPerMinute 
        || ticks == TimeSpan.TicksPerSecond 
        || ticks == TimeSpan.TicksPerMillisecond;

    // /programming/21704604/have-datetime-now-return-to-the-nearest-second
    return isValid 
        ? DateTime.SpecifyKind(
            new DateTime(
                dateTime.Ticks - (dateTime.Ticks % ticks)
            ),
            dateTime.Kind
        )
        : throw new ArgumentException("Invalid ticks value given. Only TimeSpan tick values are allowed.");
}

तो आप इस तरह विधि का उपयोग कर सकते हैं:

DateTime dateTime = DateTime.UtcNow.Truncate(TimeSpan.TicksPerMillisecond);

dateTime.Kind => DateTimeKind.Utc

-1

मुझे पता है कि उत्तर काफी देर से है, लेकिन मिलीसेकंड से छुटकारा पाने का सबसे अच्छा तरीका है

var currentDateTime = DateTime.Now.ToString("s");

चर के मूल्य को प्रिंट करने का प्रयास करें, यह बिना मिलिसेकंड के, दिनांक समय दिखाएगा।


1
यह आदर्श नहीं है। आपको एक स्ट्रिंग मिल गई है और डेटाइम नहीं है।
जेफ पुतज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.