c# - वर्ष/महीना/सप्ताह/दिन में दो तिथियों के बीच अंतर कैसे प्राप्त करें?




.net datetime (14)

एक कुशल तरीके से वर्ष / महीना / सप्ताह / दिन में दो तिथियों के बीच अंतर कैसे प्राप्त करें?

जैसे। दो तिथियों के बीच अंतर 1 साल, 2 महीने, 3 सप्ताह, 4 दिन है।

अंतर दो तारीखों के बीच वर्ष (ओं), सप्ताह (ओं) और दिन (ओं) की गिनती का प्रतिनिधित्व करता है।


आंशिक रूप से इस प्रश्न का सही उत्तर देने की कोशिश करने के लिए तैयारी के रूप में (और यहां तक ​​कि निश्चित रूप से भी ...), आंशिक रूप से यह जांचने के लिए कि एसओ पर चिपकाए गए कोड पर कितना भरोसा हो सकता है, और आंशिक रूप से बग खोजने में एक अभ्यास के रूप में, मैंने एक गुच्छा बनाया इस प्रश्न के लिए यूनिट परीक्षण, और उन्हें इस पृष्ठ से कई प्रस्तावित समाधानों और दो डुप्लिकेट के लिए लागू किया।

परिणाम निर्णायक हैं: कोड योगदानों में से एक भी प्रश्न का सही जवाब नहीं देता है। अपडेट करें: अब मेरे पास इस प्रश्न के चार सही समाधान हैं, जिनमें मेरा अपडेट शामिल है, नीचे दिए गए अपडेट देखें।

कोड परीक्षण किया

इस सवाल से, मैंने निम्नलिखित उपयोगकर्ताओं द्वारा कोड का परीक्षण किया: मोहम्मद इजास नासीरुदेन, रफिन, मालु एमएन, डेव, पीके।, जानी, एलसी।

ये सभी उत्तर थे जो उनके कोड में तीनों वर्षों, महीनों और दिनों को प्रदान करते थे। ध्यान दें कि इनमें से दो, डेव और जानी ने वर्षों की गिनती के बाद शेष महीनों की संख्या और महीनों की गिनती के बाद शेष दिनों की संख्या के बजाय दिन और महीनों की कुल संख्या दी। मुझे लगता है कि ओपी क्या चाहता था के जवाब में जवाब गलत हैं, लेकिन यूनिट परीक्षण स्पष्ट रूप से इन मामलों में आपको ज्यादा नहीं बताते हैं। (ध्यान दें कि जानी के मामले में यह मेरी त्रुटि थी और उसका कोड वास्तव में सही था - नीचे अपडेट 4 देखें)

जॉन स्कीट, अघसोलेमिनी, मुकेश कुमार, रिचर्ड, कॉलिन, शीयर के जवाब, मैंने देखा, चाल्की और एंडी, अपूर्ण थे। इसका मतलब यह नहीं है कि उत्तर कोई अच्छा नहीं थे, वास्तव में उनमें से कई समाधान के लिए उपयोगी योगदान हैं। इसका मतलब यह है कि कोड दो DateTime नहीं ले रहा था और 3 int लौटा रहा था जिसे मैं ठीक से परीक्षण कर सकता था। इनमें से चार हालांकि TimeSpan का उपयोग करने के बारे में बात करते हैं। जैसा कि कई लोगों ने उल्लेख किया है, TimeSpan दिनों से बड़े किसी भी चीज की गणना नहीं करता है।

मेरे द्वारा परीक्षण किए गए अन्य उत्तरों से थे

  • प्रश्न 3054715 - ल्यूकएच, हो 1 और यह। ___curious_geek
  • प्रश्न 6260372 - चक रोस्टेंस और जानी (इस सवाल के समान जवाब)
  • प्रश्न 9 (!) - डायलन हेस, जॉन और राजेश्वरन एसपी

यह .___ curious_geek का उत्तर उस पृष्ठ पर कोड है जिसे उसने लिंक किया था, जो मुझे नहीं लगता कि उसने लिखा था। जानी का जवाब एकमात्र ऐसा है जो बाहरी लाइब्रेरी का उपयोग करता है, .NET के लिए टाइम पीरियड लाइब्रेरी।

इन सभी सवालों पर अन्य सभी उत्तरों अधूरे लगते थे। प्रश्न 9 वर्षों से उम्र के बारे में है, और तीन उत्तरों वे हैं जो संक्षिप्त और गणना किए गए वर्षों, महीनों और दिनों से अधिक हो गए हैं। अगर किसी को इस प्रश्न के आगे डुप्लिकेट मिलते हैं तो कृपया मुझे बताएं।

मैंने कैसे परीक्षण किया

काफी सरल: मैंने एक इंटरफेस बनाया

public interface IDateDifference
{
  void SetDates(DateTime start, DateTime end);
  int GetYears();
  int GetMonths();
  int GetDays();

}

प्रत्येक उत्तर के लिए मैंने प्रतिलिपि और चिपकाए गए कोड का उपयोग आधार के रूप में इस इंटरफ़ेस को लागू करने वाली कक्षा लिखी है। बेशक मुझे विभिन्न हस्ताक्षर आदि के साथ कार्यों को अनुकूलित करना पड़ा, लेकिन मैंने सभी तर्क कोड को संरक्षित करने के लिए न्यूनतम संपादन करने की कोशिश की।

मैंने एक अमूर्त जेनेरिक वर्ग में एनयूनीट परीक्षणों का एक गुच्छा लिखा था

[TestFixture]
public abstract class DateDifferenceTests<DDC> where DDC : IDateDifference, new()

और एक खाली व्युत्पन्न कक्षा जोड़ा

public class Rajeshwaran_S_P_Test : DateDifferenceTests<Rajeshwaran_S_P>
{
}

प्रत्येक IDateDifference वर्ग के लिए स्रोत फ़ाइल में।

NUnit बाकी करने के लिए पर्याप्त चालाक है।

जाँच

इनमें से कुछ पहले से ही लिखे गए थे और बाकी को कामकाजी कार्यान्वयन की कोशिश करने और तोड़ने के लिए लिखा गया था।

[TestFixture]
public abstract class DateDifferenceTests<DDC> where DDC : IDateDifference, new()
{
  protected IDateDifference ddClass;

  [SetUp]
  public void Init()
  {
    ddClass = new DDC();
  }

  [Test]
  public void BasicTest()
  {
    ddClass.SetDates(new DateTime(2012, 12, 1), new DateTime(2012, 12, 25));
    CheckResults(0, 0, 24);
  }

  [Test]
  public void AlmostTwoYearsTest()
  {
    ddClass.SetDates(new DateTime(2010, 8, 29), new DateTime(2012, 8, 14));
    CheckResults(1, 11, 16);
  }

  [Test]
  public void AlmostThreeYearsTest()
  {
    ddClass.SetDates(new DateTime(2009, 7, 29), new DateTime(2012, 7, 14));
    CheckResults(2, 11, 15);
  }

  [Test]
  public void BornOnALeapYearTest()
  {
    ddClass.SetDates(new DateTime(2008, 2, 29), new DateTime(2009, 2, 28));
    CheckControversialResults(0, 11, 30, 1, 0, 0);
  }

  [Test]
  public void BornOnALeapYearTest2()
  {
    ddClass.SetDates(new DateTime(2008, 2, 29), new DateTime(2009, 3, 1));
    CheckControversialResults(1, 0, 0, 1, 0, 1);
  }


  [Test]
  public void LongMonthToLongMonth()
  {
    ddClass.SetDates(new DateTime(2010, 1, 31), new DateTime(2010, 3, 31));
    CheckResults(0, 2, 0);
  }

  [Test]
  public void LongMonthToLongMonthPenultimateDay()
  {
    ddClass.SetDates(new DateTime(2009, 1, 31), new DateTime(2009, 3, 30));
    CheckResults(0, 1, 30);
  }

  [Test]
  public void LongMonthToShortMonth()
  {
    ddClass.SetDates(new DateTime(2009, 8, 31), new DateTime(2009, 9, 30));
    CheckControversialResults(0, 1, 0, 0, 0, 30);
  }

  [Test]
  public void LongMonthToPartWayThruShortMonth()
  {
    ddClass.SetDates(new DateTime(2009, 8, 31), new DateTime(2009, 9, 10));
    CheckResults(0, 0, 10);
  }

  private void CheckResults(int years, int months, int days)
  {
    Assert.AreEqual(years, ddClass.GetYears());
    Assert.AreEqual(months, ddClass.GetMonths());
    Assert.AreEqual(days, ddClass.GetDays());
  }

  private void CheckControversialResults(int years, int months, int days,
    int yearsAlt, int monthsAlt, int daysAlt)
  {
    // gives the right output but unhelpful messages
    bool success = ((ddClass.GetYears() == years
                     && ddClass.GetMonths() == months
                     && ddClass.GetDays() == days)
                    ||
                    (ddClass.GetYears() == yearsAlt
                     && ddClass.GetMonths() == monthsAlt
                     && ddClass.GetDays() == daysAlt));

    Assert.IsTrue(success);
  }
}

अधिकांश नाम थोड़ा मूर्ख हैं और वास्तव में यह नहीं बताते कि कोड परीक्षण में विफल क्यों हो सकता है, हालांकि दो तिथियों को देखते हुए और उत्तर (परीक्षा) को समझने के लिए पर्याप्त होना चाहिए।

ऐसे दो कार्य हैं जो सभी Assert s, CheckResults() और CheckResults() CheckControversialResults() । ये टाइपिंग को सहेजने और सही परिणाम देने के लिए अच्छी तरह से काम करते हैं, लेकिन दुर्भाग्यवश वे यह देखने में कठोर बनाते हैं कि क्या गलत हुआ (क्योंकि CheckControversialResults() में CheckControversialResults() "अनुमानित सत्य" के साथ विफल कर देगा, यह CheckControversialResults() कि कौन सा मान गलत था। किसी के पास ऐसा करने का एक बेहतर तरीका है (हर बार एक ही चेक लिखने से बचें, लेकिन अधिक उपयोगी त्रुटि संदेश हैं) कृपया मुझे बताएं।

CheckControversialResults() का उपयोग कुछ मामलों के लिए किया जाता है जहां सही पर दो अलग-अलग राय लगती हैं। मेरे पास मेरी राय है, लेकिन मैंने सोचा कि मुझे यहां स्वीकार किए जाने में उदार होना चाहिए। इसका अर्थ यह तय करना है कि 2 9 फरवरी के बाद एक साल 28 फरवरी या 1 मार्च है।

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

किसी भी परीक्षण में दिन का समय शामिल नहीं होता है - सभी DateTime मध्यरात्रि में होते हैं। समय सहित, जब तक यह स्पष्ट हो जाता है कि कैसे दिन भर काम करता है और नीचे काम करता है (मुझे लगता है कि यह है), और भी त्रुटियों को दिखा सकता है।

परिणाम

परिणामों का पूरा स्कोरबोर्ड निम्नानुसार है:

ChuckRostance_Test 3 failures               S S S F S S F S F
Dave_Test 6 failures                        F F S F F F F S S
Dylan_Hayes_Test 9 failures                 F F F F F F F F F
ho1_Test 3 failures                         F F S S S S F S S
Jani_Test 6 failures                        F F S F F F F S S
Jon_Test 1 failure                          S S S S S S F S S
lc_Test 2 failures                          S S S S S F F S S
LukeH_Test 1 failure                        S S S S S S F S S
Malu_MN_Test 1 failure                      S S S S S S S F S
Mohammed_Ijas_Nasirudeen_Test 2 failures    F S S F S S S S S
pk_Test 6 failures                          F F F S S F F F S
Rajeshwaran_S_P_Test 7 failures             F F S F F S F F F
ruffin_Test 3 failures                      F S S F S S F S S
this_curious_geek_Test 2 failures           F S S F S S S S S

लेकिन ध्यान दें कि जानी का समाधान वास्तव में सही था और सभी परीक्षणों को पारित किया गया - नीचे अपडेट 4 देखें।

कॉलम परीक्षण नाम के वर्णानुक्रम में हैं:

  • AlmostThreeYearsTest
  • AlmostTwoYearsTest
  • BasicTest
  • BornOnALeapYearTest
  • BornOnALeapYearTest2
  • LongMonthToLongMonth
  • LongMonthToLongMonthPenultimateDay
  • LongMonthToPartWayThruShortMonth
  • LongMonthToShortMonth

तीन उत्तरों, जॉन, ल्यूकएच और मनु एमएन के प्रत्येक परीक्षा में केवल 1 परीक्षण विफल रहे। ध्यान रखें कि इन परीक्षणों को शायद उन उत्तरों में त्रुटियों को हल करने के लिए विशेष रूप से लिखा गया था।

प्रत्येक परीक्षण कोड के कम से कम एक टुकड़े से पारित किया गया था, जो थोड़ा आश्वस्त है कि कोई भी परीक्षण गलत नहीं है।

कुछ उत्तरों ने कई परीक्षणों में असफल रहा। मुझे आशा है कि कोई भी ऐसा नहीं मानता कि यह उस पोस्टर के प्रयासों की निंदा है। सबसे पहले सफलताओं की संख्या काफी मनमानी है क्योंकि परीक्षण प्रश्न स्थान के समस्या क्षेत्रों को समान रूप से कवर नहीं करते हैं। दूसरा, यह उत्पादन कोड नहीं है - उत्तर पोस्ट किए गए हैं ताकि लोग उनसे सीख सकें, उन्हें अपने कार्यक्रमों में बिल्कुल कॉपी न करें। कोड जो बहुत सारे परीक्षणों में विफल रहता है, इसमें अभी भी बहुत अच्छे विचार हो सकते हैं। कम से कम एक टुकड़ा जो कई परीक्षणों में असफल रहा, उसमें एक छोटी सी बग थी जिसे मैंने ठीक नहीं किया था। मैं इस परियोजना को इतना दिलचस्प बनाने के लिए, हर किसी के साथ अपना काम साझा करने का समय लेने वाले किसी भी व्यक्ति का आभारी हूं।

मेरे निष्कर्ष

वहा तीन है:

  1. कैलेंडर कठिन हैं। मैंने नौ परीक्षण लिखे, जिनमें तीन शामिल हैं जहां दो उत्तर संभव हैं। कुछ परीक्षण जहां मेरे पास केवल एक जवाब था, सर्वसम्मति से सहमत नहीं हो सकता है। जब हम कहते हैं कि '1 महीने बाद' या '2 साल पहले' कई स्थितियों में मुश्किल है तो बस हम क्या सोचते हैं। और इस कोड में से कोई भी चीज की सभी जटिलताओं से निपटना नहीं था जैसे लीप साल के दौरान काम करना। यह सभी तारीखों को संभालने के लिए लाइब्रेरी कोड का उपयोग करता है। यदि आप कल्पना करते हैं कि दिन, सप्ताह, महीनों और वर्षों में समय बताने के लिए 'spec' की कल्पना की जाती है, तो क्रूरता के सभी प्रकार होते हैं। क्योंकि हम इसे प्राथमिक विद्यालय के बाद से बहुत अच्छी तरह से जानते हैं, और इसे हर रोज इस्तेमाल करते हैं, हम कई मूर्खता के लिए अंधे हैं। सवाल अकादमिक नहीं है - बॉन्ड और अन्य वित्तीय उत्पादों के लिए लेखांकन सॉफ्टवेयर में वर्षों, तिमाहियों और महीनों में समय अवधि के विभिन्न प्रकार के अपघटन आवश्यक हैं।

  2. सही कोड लिखना मुश्किल है। बहुत सारी बगियां थीं। किसी टिप्पणीकर्ता द्वारा इंगित किए बिना बग की संभावनाओं के मुकाबले थोड़ा अधिक अस्पष्ट विषयों या कम लोकप्रिय प्रश्नों में, इस प्रश्न के मुकाबले बहुत अधिक है। आपको वास्तव में कभी नहीं करना चाहिए, कभी भी यह समझने के बिना एसओ से अपने प्रोग्राम में कोड कॉपी न करें। इसका फ्लिपसाइड यह है कि आपको शायद अपने उत्तर में कोड नहीं लिखना चाहिए जो प्रतिलिपि बनाने और पेस्ट करने के लिए तैयार है, बल्कि बुद्धिमान और अभिव्यक्तिपूर्ण छद्म कोड है जो किसी को समाधान को समझने और अपने स्वयं के संस्करणों को लागू करने की अनुमति देता है (अपनी स्वयं की बग के साथ !)

  3. यूनिट परीक्षण सहायक हैं। जब भी मैं इसके चारों ओर घूमता हूं (किसी और के लिए छुपे हुए, ग़लत धारणाओं को ढूंढने के लिए!) करने के लिए मेरा स्वयं का समाधान पोस्ट करना अभी भी मेरा मतलब है) ऐसा करना यूनिट परीक्षणों में उन्हें बदलकर 'बग को बचाने' का एक बड़ा उदाहरण था कोड के अगले संस्करण को ठीक करें।

अद्यतन करें

पूरी परियोजना अब https://github.com/jwg4/date-difference पर है, इसमें मेरा अपना प्रयास jwg.cs , जो वर्तमान में मेरे पास मौजूद सभी परीक्षणों को पास करता है, जिनमें कुछ नए शामिल हैं जो दिन के हैंडलिंग के उचित समय की जांच करते हैं । इस और अन्य कार्यान्वयन या प्रश्न का उत्तर देने के लिए बेहतर कोड तोड़ने के लिए या तो अधिक परीक्षण जोड़ने के लिए स्वतंत्र महसूस करें।

अद्यतन 2

@ मैटजोहनसन ने एक कार्यान्वयन जोड़ा है जो जॉन स्कीट के नोडाटाइम का उपयोग करता है। यह सभी मौजूदा परीक्षण पास करता है।

अद्यतन 3

जिथब पर परियोजना में दो तिथियों के बीच महीनों में अंतर के लिए @ किर्कवॉल का जवाब जोड़ा गया है। यह सभी मौजूदा परीक्षण पास करता है।

अद्यतन 4

@ जनी ने एक टिप्पणी में बताया कि मैंने अपना कोड गलत तरीके से इस्तेमाल किया था। उन्होंने उन तरीकों का सुझाव दिया जो वर्षों, महीनों और दिनों को सही ढंग से गिनते थे, (कुछ ऐसे लोगों के साथ जो दिन और महीनों की कुल संख्या की गणना करते हैं, बचे हुए नहीं) हालांकि मैंने गलती से गलत परीक्षणों को अपने टेस्ट कोड में इस्तेमाल किया। मैंने अपने कोड के चारों ओर अपने रैपर को सही किया है और अब यह सभी परीक्षणों को पास करता है। अब चार सही समाधान हैं, जिनमें से जनी पहली थीं। दो उपयोग पुस्तकालय (Intenso.TimePeriod और NodaTime) और दो स्क्रैच से लिखे गए हैं।


खैर, @ जोन स्कीट, यदि हम ओपी के मुताबिक दिन की तुलना में अधिक ग्रेन्युलर (और अभी भी दिन भर में बड़ी इकाइयों में रोलिंग करने के बारे में चिंतित नहीं हैं), तो यह वास्तव में सी # में मुश्किल नहीं है। तारीख गणित इतना कठिन बनाता है कि प्रत्येक समग्र इकाई में इकाइयों की संख्या अक्सर बदल जाती है। कल्पना करें कि गैस के हर तीसरे गैलन केवल 3 क्वार्ट थे, लेकिन प्रत्येक 12 वीं 7 थी, शुक्रवार को छोड़कर, जब ...

सौभाग्य से, तारीख सबसे बड़ी पूर्णांक समारोह के माध्यम से बस एक लंबी सवारी है । ये पागल अपवाद गड़बड़ कर रहे हैं, जब तक कि आप पूरी तरह से शामिल इकाई के माध्यम से सभी तरह से नहीं गए हैं, जब यह अब एक बड़ा सौदा नहीं है। यदि आप 12/25/1900 पर पैदा हुए हैं, तो आप अभी भी छलांग वर्ष या सेकंड या डेलाइट बचत अवधि के बावजूद 12/25/2000 पर बिल्कुल 100 हैं। जैसे ही आप अंतिम समग्र इकाई बनाने वाले प्रतिशत के माध्यम से फंस गए हैं, आप एकता पर वापस आ गए हैं। आपने एक जोड़ा है, और शुरू करने के लिए मिलता है।

जो सिर्फ यह कहना है कि यदि आप महीनों से महीनों तक वर्षों कर रहे हैं, तो केवल अजीब रूप से शामिल इकाई महीने (दिनों का) है। यदि आपको उस महीने को संभालने के लिए महीने के मूल्य से उधार लेने की आवश्यकता है जहां आप अपने दिन से अधिक दिन घटा रहे हैं, तो आपको पिछले महीने के दिनों की संख्या जानने की जरूरत है। कोई अन्य outliers मायने रखता है।

और सी # आपको System.DateTime.DaysInMonth (intYear, intMonth) में देता है।

(यदि आपका महीना महीना आपके महीने से छोटा है, तो कोई समस्या नहीं है। हर साल 12 महीने होते हैं।)

और यदि हम अधिक बारीक हो जाते हैं तो वही सौदा ... आपको केवल यह जानने की जरूरत है कि आखिरी (समग्र इकाई) में कितनी (छोटी इकाइयां) हैं। एक बार जब आप अतीत हो जाते हैं, तो आपको एक और पूर्णांक मान (समग्र इकाई) मिलता है। फिर घटाएं कि आपने कितनी छोटी इकाइयों को शुरू किया था, जहां आपने किया था और फिर वापस जोड़ें कि आप अपने अब के साथ संयुक्त इकाई ब्रेक-ऑफ के पीछे कितने गए थे।

तो यहां दो तारीखों को घटाने पर मेरे पहले कट से मुझे क्या मिला है। यह काम हो सकता है। उम्मीद है कि उपयोगी है।

(संपादित करें: न्यूमोनथ> ओल्डमोन्थ न्यूमोनथ> = ओल्डमोन्थ की जांच करें, क्योंकि अगर महीने समान हैं (दिन के लिए डेट) तो हमें उधार लेने की आवश्यकता नहीं है। यही है, 11 नवंबर 2011 से घटाकर 9 नवंबर 2010 -1 वर्ष दे रहा था , 12 महीने, 2 दिन (यानी, 2 दिन, लेकिन रॉयलल्टी की आवश्यकता नहीं होने पर शाही हम उधार लेते थे।)

(संपादित करें: महीने = महीना की जांच करनी थी जब हमें dteNow.Day और dteNow.Day <dteThen.Day से दिन निकालने के लिए दिन उधार लेने की आवश्यकता थी, क्योंकि हमें 11 महीने और अतिरिक्त दिन प्राप्त करने के लिए एक वर्ष घटाना पड़ा ठीक है, तो कुछ आउटलाइर्स हैं। ^ डीआई सोचते हैं कि मैं अभी बंद हूं।)

private void Form1_Load(object sender, EventArgs e) {
DateTime dteThen = DateTime.Parse("3/31/2010");
DateTime dteNow = DateTime.Now;

int intDiffInYears = 0;
int intDiffInMonths = 0;
int intDiffInDays = 0;


if (dteNow.Month >= dteThen.Month)
{
    if (dteNow.Day >= dteThen.Day)
    {   // this is a best case, easy subtraction situation
        intDiffInYears = dteNow.Year - dteThen.Year;
        intDiffInMonths = dteNow.Month - dteThen.Month;
        intDiffInDays = dteNow.Day - dteThen.Day;
    }
    else
    {   // else we need to substract one from the month diff (borrow the one)
        // and days get wacky.

        // Watch for the outlier of Month = Month with DayNow < DayThen, as then we've 
        // got to subtract one from the year diff to borrow a month and have enough
        // days to subtract Then from Now.
        if (dteNow.Month == dteThen.Month)
        {
            intDiffInYears = dteNow.Year - dteThen.Year - 1;
            intDiffInMonths = 11; // we borrowed a year and broke ONLY 
            // the LAST month into subtractable days
            // Stay with me -- because we borrowed days from the year, not the month,
            // this is much different than what appears to be a similar calculation below.
            // We know we're a full intDiffInYears years apart PLUS eleven months.
            // Now we need to know how many days occurred before dteThen was done with 
            // dteThen.Month.  Then we add the number of days we've "earned" in the current
            // month.  
            //
            // So 12/25/2009 to 12/1/2011 gives us 
            // 11-9 = 2 years, minus one to borrow days = 1 year difference.
            // 1 year 11 months - 12 months = 11 months difference
            // (days from 12/25 to the End Of Month) + (Begin of Month to 12/1) = 
            //                (31-25)                +       (0+1)              =
            //                   6                   +         1                = 
            //                                  7 days diff
            //
            // 12/25/2009 to 12/1/2011 is 1 year, 11 months, 7 days apart.  QED.

            int intDaysInSharedMonth = System.DateTime.DaysInMonth(dteThen.Year, dteThen.Month);
            intDiffInDays = intDaysInSharedMonth - dteThen.Day + dteNow.Day;
        }
        else
        {
            intDiffInYears = dteNow.Year - dteThen.Year;
            intDiffInMonths = dteNow.Month - dteThen.Month - 1;

            // So now figure out how many more days we'd need to get from dteThen's 
            // intDiffInMonth-th month to get to the current month/day in dteNow.
            // That is, if we're comparing 2/8/2011 to 11/7/2011, we've got (10/8-2/8) = 8
            // full months between the two dates.  But then we've got to go from 10/8 to
            // 11/07.  So that's the previous month's (October) number of days (31) minus
            // the number of days into the month dteThen went (8), giving the number of days
            // needed to get us to the end of the month previous to dteNow (23).  Now we
            // add back the number of days that we've gone into dteNow's current month (7)
            // to get the total number of days we've gone since we ran the greatest integer
            // function on the month difference (23 to the end of the month + 7 into the
            // next month == 30 total days.  You gotta make it through October before you 
            // get another month, G, and it's got 31 days).

            int intDaysInPrevMonth = System.DateTime.DaysInMonth(dteNow.Year, (dteNow.Month - 1));
            intDiffInDays = intDaysInPrevMonth - dteThen.Day + dteNow.Day;
        }
    }
}
else
{
    // else dteThen.Month > dteNow.Month, and we've got to amend our year subtraction
    // because we haven't earned our entire year yet, and don't want an obo error.
    intDiffInYears = dteNow.Year - dteThen.Year - 1;

    // So if the dates were THEN: 6/15/1999 and NOW: 2/20/2010...
    // Diff in years is 2010-1999 = 11, but since we're not to 6/15 yet, it's only 10.
    // Diff in months is (Months in year == 12) - (Months lost between 1/1/1999 and 6/15/1999
    // when dteThen's clock wasn't yet rolling == 6) = 6 months, then you add the months we
    // have made it into this year already.  The clock's been rolling through 2/20, so two months.
    // Note that if the 20 in 2/20 hadn't been bigger than the 15 in 6/15, we're back to the
    // intDaysInPrevMonth trick from earlier.  We'll do that below, too.
    intDiffInMonths = 12 - dteThen.Month + dteNow.Month;

    if (dteNow.Day >= dteThen.Day)
    {
        intDiffInDays = dteNow.Day - dteThen.Day;
    }
    else
    {
        intDiffInMonths--;  // subtract the month from which we're borrowing days.

        // Maybe we shoulda factored this out previous to the if (dteNow.Month > dteThen.Month)
        // call, but I think this is more readable code.
        int intDaysInPrevMonth = System.DateTime.DaysInMonth(dteNow.Year, (dteNow.Month - 1));
        intDiffInDays = intDaysInPrevMonth - dteThen.Day + dteNow.Day;
    }

}

this.addToBox("Years: " + intDiffInYears + " Months: " + intDiffInMonths + " Days: " + intDiffInDays); // adds results to a rich text box.

}

यदि आप DateTime, दो उदाहरण घटाते हैं DateTime, वह TimeSpan का एक उदाहरण वापस कर देगा, जो दो तिथियों के बीच अंतर का प्रतिनिधित्व करेगा।


यह वास्तव में काफी मुश्किल है। एक ही परिणाम में दिन की एक अलग संख्या का परिणाम हो सकता है। उदाहरण के लिए:

  • 1 9 जून 2008 से 1 9 जून 2010 = 2 साल, लेकिन 365 * 2 दिन भी

  • 1 9 जून 2006 से 1 9 जून 2008 = 2 साल, लेकिन लीप वर्षों के कारण 365 + 366 दिन भी

आप साल तक घटाना चाहते हैं जब तक आप उस बिंदु तक नहीं पहुंच जाते जहां आपको दो तिथियां मिलती हैं जो एक साल से भी कम होती हैं। फिर महीनों को घटाना जब तक आप उस बिंदु तक नहीं पहुंच जाते जहां आपको दो तिथियां मिलती हैं जो एक महीने से भी कम होती हैं।

आगे भ्रम: जब आप "30 मार्च" की तारीख से शुरू कर सकते हैं तो महीनों को घटाना (या जोड़ना) मुश्किल है - उससे पहले एक महीने क्या है?

यहां तक ​​कि आगे भ्रम (प्रासंगिक नहीं हो सकता है): यहां तक ​​कि एक दिन हमेशा 24 घंटे नहीं होता है। डेलाइट किसी को बचा रहा है?

और भी भ्रम (लगभग निश्चित रूप से प्रासंगिक नहीं ): यहां तक ​​कि एक मिनट हमेशा 60 सेकंड नहीं होता है। लीप सेकंड बहुत उलझन में हैं ...

मेरे पास अभी यह करने के सही तरीके से काम करने का समय नहीं है - यह उत्तर ज्यादातर इस तथ्य को बढ़ाने के लिए है कि यह लगभग उतना आसान नहीं है जितना यह ध्वनि हो सकता है।

संपादित करें: दुर्भाग्यवश मेरे पास इसका जवाब देने के लिए पर्याप्त समय नहीं होगा। मैं सुझाव दूंगा कि आप एक Period प्रतिनिधित्व करने वाली संरचना को परिभाषित करके शुरू करें:

public struct Period
{
    private readonly int days;
    public int Days { get { return days; } }
    private readonly int months;
    public int Months { get { return months; } }
    private readonly int years;
    public int Years { get { return years; } }

    public Period(int years, int months, int days)
    {
        this.years = years;
        this.months = months;
        this.days = days;
    }

    public Period WithDays(int newDays)
    {
        return new Period(years, months, newDays);
    }

    public Period WithMonths(int newMonths)
    {
        return new Period(years, newMonths, days);
    }

    public Period WithYears(int newYears)
    {
        return new Period(newYears, months, days);
    }

    public static DateTime operator +(DateTime date, Period period)
    {
        // TODO: Implement this!
    }

    public static Period Difference(DateTime first, DateTime second)
    {
        // TODO: Implement this!
    }
}

मेरा सुझाव है कि आप पहले + ऑपरेटर को कार्यान्वित करें, जिसे Difference विधि को सूचित करना चाहिए - आपको यह सुनिश्चित करना चाहिए कि first + (Period.Difference(first, second)) == second first / second मानों के लिए।

पूरी तरह से यूनिट परीक्षणों को लिखने के साथ शुरू करें - शुरुआत में "आसान" मामले, फिर लीप वर्षों से जुड़े मुश्किल लोगों पर जाएं। मुझे पता है कि सामान्य दृष्टिकोण एक समय में एक परीक्षण लिखना है, लेकिन आप किसी भी कार्यान्वयन कार्य शुरू करने से पहले व्यक्तिगत रूप से उनमें से एक समूह को समझना चाहते हैं।

अपने आप को इसे ठीक से लागू करने के लिए एक दिन दें। यह मुश्किल चीजें है।

ध्यान दें कि मैंने यहां सप्ताह छोड़े हैं - कम से कम मूल्य कम है, क्योंकि यह हमेशा 7 दिन होता है। तो एक (सकारात्मक) अवधि दी गई, आपके पास होगा:

int years = period.Years;
int months = period.Months;
int weeks = period.Days / 7;
int daysWithinWeek = period.Days % 7;

(मेरा सुझाव है कि आप नकारात्मक अवधि के बारे में भी सोचने से बचें - सुनिश्चित करें कि सब कुछ सकारात्मक है, हर समय।)


वर्ष / महीनों / सप्ताहों की सही अंतर गणना के लिए, CultureInfo का कैलेंडर माना जाना चाहिए:

  • छलांग बनाम गैर लीप साल
  • दिनों की अलग-अलग गिनती के साथ महीनों
  • सप्ताहों की अलग-अलग गिनती के साथ सालों (सप्ताह के पहले दिन और कैलेंडर सप्ताह के नियम के अनुसार अलग-अलग)

.NET के लिए समय अवधि पुस्तकालय की डेटडिफ कक्षा इन सभी कारकों का सम्मान करती है:

// ----------------------------------------------------------------------
public void DateDiffSample()
{
  DateTime date1 = new DateTime( 2009, 11, 8, 7, 13, 59 );
  Console.WriteLine( "Date1: {0}", date1 );
  // > Date1: 08.11.2009 07:13:59
  DateTime date2 = new DateTime( 2011, 3, 20, 19, 55, 28 );
  Console.WriteLine( "Date2: {0}", date2 );
  // > Date2: 20.03.2011 19:55:28

  DateDiff dateDiff = new DateDiff( date1, date2 );

  // differences
  Console.WriteLine( "DateDiff.Years: {0}", dateDiff.Years );
  // > DateDiff.Years: 1
  Console.WriteLine( "DateDiff.Quarters: {0}", dateDiff.Quarters );
  // > DateDiff.Quarters: 5
  Console.WriteLine( "DateDiff.Months: {0}", dateDiff.Months );
  // > DateDiff.Months: 16
  Console.WriteLine( "DateDiff.Weeks: {0}", dateDiff.Weeks );
  // > DateDiff.Weeks: 70
  Console.WriteLine( "DateDiff.Days: {0}", dateDiff.Days );
  // > DateDiff.Days: 497
  Console.WriteLine( "DateDiff.Weekdays: {0}", dateDiff.Weekdays );
  // > DateDiff.Weekdays: 71
  Console.WriteLine( "DateDiff.Hours: {0}", dateDiff.Hours );
  // > DateDiff.Hours: 11940
  Console.WriteLine( "DateDiff.Minutes: {0}", dateDiff.Minutes );
  // > DateDiff.Minutes: 716441
  Console.WriteLine( "DateDiff.Seconds: {0}", dateDiff.Seconds );
  // > DateDiff.Seconds: 42986489

  // elapsed
  Console.WriteLine( "DateDiff.ElapsedYears: {0}", dateDiff.ElapsedYears );
  // > DateDiff.ElapsedYears: 1
  Console.WriteLine( "DateDiff.ElapsedMonths: {0}", dateDiff.ElapsedMonths );
  // > DateDiff.ElapsedMonths: 4
  Console.WriteLine( "DateDiff.ElapsedDays: {0}", dateDiff.ElapsedDays );
  // > DateDiff.ElapsedDays: 12
  Console.WriteLine( "DateDiff.ElapsedHours: {0}", dateDiff.ElapsedHours );
  // > DateDiff.ElapsedHours: 12
  Console.WriteLine( "DateDiff.ElapsedMinutes: {0}", dateDiff.ElapsedMinutes );
  // > DateDiff.ElapsedMinutes: 41
  Console.WriteLine( "DateDiff.ElapsedSeconds: {0}", dateDiff.ElapsedSeconds );
  // > DateDiff.ElapsedSeconds: 29

  // description
  Console.WriteLine( "DateDiff.GetDescription(1): {0}", dateDiff.GetDescription( 1 ) );
  // > DateDiff.GetDescription(1): 1 Year
  Console.WriteLine( "DateDiff.GetDescription(2): {0}", dateDiff.GetDescription( 2 ) );
  // > DateDiff.GetDescription(2): 1 Year 4 Months
  Console.WriteLine( "DateDiff.GetDescription(3): {0}", dateDiff.GetDescription( 3 ) );
  // > DateDiff.GetDescription(3): 1 Year 4 Months 12 Days
  Console.WriteLine( "DateDiff.GetDescription(4): {0}", dateDiff.GetDescription( 4 ) );
  // > DateDiff.GetDescription(4): 1 Year 4 Months 12 Days 12 Hours
  Console.WriteLine( "DateDiff.GetDescription(5): {0}", dateDiff.GetDescription( 5 ) );
  // > DateDiff.GetDescription(5): 1 Year 4 Months 12 Days 12 Hours 41 Mins
  Console.WriteLine( "DateDiff.GetDescription(6): {0}", dateDiff.GetDescription( 6 ) );
  // > DateDiff.GetDescription(6): 1 Year 4 Months 12 Days 12 Hours 41 Mins 29 Secs
} // DateDiffSample

डेटडिफ क्वार्टर के अंतर की भी गणना करता है।


System.Data.Linq नामस्थान और इसकी SqlMethods.DateDiffMonth विधि का उपयोग करने के बारे में क्या?

उदाहरण के लिए, कहें:

DateTime starDT = {01-Jul-2009 12:00:00 AM}
DateTime endDT = {01-Nov-2009 12:00:00 AM}

फिर:

int monthDiff = System.Data.Linq.SqlClient.SqlMethods.DateDiffMonth(startDT, endDT);

==> 4

SqlMethods वर्ग में अन्य SqlMethods स्थैतिक विधियां हैं।


Days: (endDate - startDate).Days
Weeks: (endDate - startDate).Days / 7
Years: Months / 12
Months: A TimeSpan only provides Days, so use the following code to get the number of whole months between a specified start and end date. For example, the number of whole months between 01/10/2000 and 02/10/2000 is 1. The the number of whole months between 01/10/2000 and 02/09/2000 is 0.

    public int getMonths(DateTime startDate, DateTime endDate)
    {
        int months = 0;

        if (endDate.Month <= startDate.Month)
        {
            if (endDate.Day < startDate.Day)
            {
                months = (12 * (endDate.Year - startDate.Year - 1))
                       + (12 - startDate.Month + endDate.Month - 1);
            }
            else if (endDate.Month < startDate.Month)
            {
                months = (12 * (endDate.Year - startDate.Year - 1))
                       + (12 - startDate.Month + endDate.Month);
            }
            else  // (endDate.Month == startDate.Month) && (endDate.Day >= startDate.Day)
            {
                months = (12 * (endDate.Year - startDate.Year));
            }
        }
        else if (endDate.Day < startDate.Day)
        {
            months = (12 * (endDate.Year - startDate.Year))
                   + (endDate.Month - startDate.Month) - 1;
        }
        else  // (endDate.Month > startDate.Month) && (endDate.Day >= startDate.Day)
        {
            months = (12 * (endDate.Year - startDate.Year))
                   + (endDate.Month - startDate.Month);
        }

        return months;
    }

I came across this post while looking to solve a similar problem. I was trying to find the age of an animal in units of Years, Months, Weeks, and Days. Those values are then displayed in SpinEdits where the user can manually change the values to find/estimate a birth date. When my form was passed a birth date from a month with less than 31 days, the value calculated was 1 day off. I based my solution off of Ic's answer above.

Main calculation method that is called after my form loads.

        birthDateDisplay.Text = birthDate.ToString("MM/dd/yyyy");

        DateTime currentDate = DateTime.Now;

        Int32 numOfDays = 0; 
        Int32 numOfWeeks = 0;
        Int32 numOfMonths = 0; 
        Int32 numOfYears = 0; 

        // changed code to follow this model http://.com/posts/1083990/revisions
        //years 
        TimeSpan diff = currentDate - birthDate;
        numOfYears = diff.Days / 366;
        DateTime workingDate = birthDate.AddYears(numOfYears);

        while (workingDate.AddYears(1) <= currentDate)
        {
            workingDate = workingDate.AddYears(1);
            numOfYears++;
        }

        //months
        diff = currentDate - workingDate;
        numOfMonths = diff.Days / 31;
        workingDate = workingDate.AddMonths(numOfMonths);

        while (workingDate.AddMonths(1) <= currentDate)
        {
            workingDate = workingDate.AddMonths(1);
            numOfMonths++;
        }

        //weeks and days
        diff = currentDate - workingDate;
        numOfWeeks = diff.Days / 7; //weeks always have 7 days

        // if bday month is same as current month and bday day is after current day, the date is off by 1 day
        if(DateTime.Now.Month == birthDate.Month && DateTime.Now.Day < birthDate.Day)
            numOfDays = diff.Days % 7 + 1;
        else
            numOfDays = diff.Days % 7;

        // If the there are fewer than 31 days in the birth month, the date calculated is 1 off
        // Dont need to add a day for the first day of the month
        int daysInMonth = 0;
        if ((daysInMonth = DateTime.DaysInMonth(birthDate.Year, birthDate.Month)) != 31 && birthDate.Day != 1)
        {
            startDateforCalc = DateTime.Now.Date.AddDays(31 - daysInMonth);
            // Need to add 1 more day if it is a leap year and Feb 29th is the date
            if (DateTime.IsLeapYear(birthDate.Year) && birthDate.Day == 29)
                startDateforCalc = startDateforCalc.AddDays(1);
        }

        yearsSpinEdit.Value = numOfYears;
        monthsSpinEdit.Value = numOfMonths;
        weeksSpinEdit.Value = numOfWeeks;
        daysSpinEdit.Value = numOfDays;

And then, in my spinEdit_EditValueChanged event handler, I calculate the new birth date starting from my startDateforCalc based on the values in the spin edits. (SpinEdits are constrained to only allow >=0)

birthDate = startDateforCalc.Date.AddYears(-((Int32)yearsSpinEdit.Value)).AddMonths(-((Int32)monthsSpinEdit.Value)).AddDays(-(7 * ((Int32)weeksSpinEdit.Value) + ((Int32)daysSpinEdit.Value)));
birthDateDisplay.Text = birthDate.ToString("MM/dd/yyyy");

I know its not the prettiest solution, but it seems to be working for me for all month lengths and years.


I was trying to find a clear answer for Years, Months and Days, and I didn't find anything clear, If you are still looking check this method:

        public static string GetDifference(DateTime d1, DateTime d2)
        {
            int[] monthDay = new int[12] { 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
            DateTime fromDate;
            DateTime toDate;
            int year;
            int month;
            int day; 
            int increment = 0;

            if (d1 > d2)
            {
                fromDate = d2;
                toDate = d1;
            }
            else
            {
                fromDate = d1;
                toDate = d2;
            } 

            // Calculating Days
            if (fromDate.Day > toDate.Day)
            {
                increment = monthDay[fromDate.Month - 1];
            }

            if (increment == -1)
            {
                if (DateTime.IsLeapYear(fromDate.Year))
                {
                    increment = 29;
                }
                else
                {
                    increment = 28;
                }
            }

            if (increment != 0)
            {
                day = (toDate.Day + increment) - fromDate.Day;
                increment = 1;
            }
            else
            {
                day = toDate.Day - fromDate.Day;
            }

            // Month Calculation
            if ((fromDate.Month + increment) > toDate.Month)
            {
                month = (toDate.Month + 12) - (fromDate.Month + increment);
                increment = 1;
            }
            else
            {
                month = (toDate.Month) - (fromDate.Month + increment);
                increment = 0;
            }

            // Year Calculation
            year = toDate.Year - (fromDate.Year + increment);

            return year + " years " + month + " months " + day + " days";
        }

If you have to find the difference between originalDate and today's date, Here is a reliable algorithm without so many condition checks.

  1. Declare a intermediateDate variable and initialize to the originalDate
  2. Find difference between years.(yearDiff)
  3. Add yearDiff to intermediateDate and check whether the value is greater than today's date.
  4. If newly obtained intermediateDate > today's date adjust the yearDiff and intermediateDate by one.
  5. Continue above steps for month and Days.

I have used System.Data.Linq functions to do find the year, month and day differences. Please find c# code below

        DateTime todaysDate = DateTime.Now;
        DateTime interimDate = originalDate;

        ///Find Year diff
        int yearDiff = System.Data.Linq.SqlClient.SqlMethods.DateDiffYear(interimDate, todaysDate);
        interimDate = interimDate.AddYears(yearDiff);
        if (interimDate > todaysDate)
        {
            yearDiff -= 1;
            interimDate = interimDate.AddYears(-1);
        }

        ///Find Month diff
        int monthDiff = System.Data.Linq.SqlClient.SqlMethods.DateDiffMonth(interimDate, todaysDate);
        interimDate = interimDate.AddMonths(monthDiff);
        if (interimDate > todaysDate)
        {
            monthDiff -= 1;
            interimDate = interimDate.AddMonths(-1);
        }

        ///Find Day diff
        int daysDiff = System.Data.Linq.SqlClient.SqlMethods.DateDiffDay(interimDate, todaysDate);

Use the Subtract method of the DateTime object which returns a TimeSpan ...

DateTime dt1 = new DateTime(2009, 3, 14);
DateTime dt2 = new DateTime(2008, 3, 15);

TimeSpan ts = dt1.Subtract(dt2);

Double days = ts.TotalDays;
Double hours = ts.TotalHours;
Double years = ts.TotalDays / 365;

    Console.WriteLine("Enter your Date of Birth to Know your Current age in DD/MM/YY Format");
    string str = Console.ReadLine();
    DateTime dt1 = DateTime.Parse(str);
    DateTime dt2 = DateTime.Parse("10/06/2012");
    int result = (dt2 - dt1).Days;
    result = result / 365;
    Console.WriteLine("Your Current age is {0} years.",result);

DateTime startTime = DateTime.Now;

DateTime endTime = DateTime.Now.AddSeconds( 75 );

TimeSpan span = endTime.Subtract ( startTime );
 Console.WriteLine( "Time Difference (seconds): " + span.Seconds );
 Console.WriteLine( "Time Difference (minutes): " + span.Minutes );
 Console.WriteLine( "Time Difference (hours): " + span.Hours );
 Console.WriteLine( "Time Difference (days): " + span.Days );

आउटपुट:

Time Difference (seconds): 15
Time Difference (minutes): 1
Time Difference (hours): 0
Time Difference (days): 0

TimeSpan period = endDate.AddDays(1) - startDate;
DateTime date = new DateTime(period.Ticks);
int totalYears = date.Year - 1;
int totalMonths = ((date.Year - 1) * 12) + date.Month - 1;
int totalWeeks = (int)period.TotalDays / 7;

date.Year - 1 because the year 0 doesn't exist. date.Month - 1, the month 0 doesn't exist





datetime