Ημέρες – Μήνες – Έτη

Όσοι θέλουν τη διαφορά ημερομηνιών σε ημέρες μήνες έτη ας μην ψάξουν παραπέρα. Εγώ τη χρειάστηκα πρόσφατα και φαίνεται να δουλεύει σωστά (όσο μπόρεσα να την τεστάρω με δεδομένα και αποτελέσματα που είχα έτοιμα σε κάποια αρχεία excel.)

HRESULT DMYYears(DATE startDate, DATE endDate, LONG* pVal)
{
    if (endDate < startDate)
        return ERROR_BAD_ARGUMENTS;

    COleDateTime dtS(startDate);
    COleDateTime dtE(endDate);

    LONG diff = dtE.GetYear() - dtS.GetYear();
    if (diff > 0)
    {
        if (dtE.GetMonth() < dtS.GetMonth())
            --diff;
        else if ((dtE.GetMonth() == dtS.GetMonth()) && (dtE.GetDay() < dtS.GetDay()))
            --diff;
    }

    *pVal = diff;
    return S_OK;
}

HRESULT DMYMonths(DATE startDate, DATE endDate, LONG* pVal)
{
    if (endDate < startDate)
        return ERROR_BAD_ARGUMENTS;

    COleDateTime dtS(startDate);
    COleDateTime dtE(endDate);

    LONG diff = dtE.GetMonth() - dtS.GetMonth();

    if (dtE.GetDay() < dtS.GetDay())
        --diff;
    if (diff < 0)
        diff += 12;

    *pVal = diff;
    return S_OK;
}

HRESULT DMYDays(DATE startDate, DATE endDate, LONG* pVal)
{
    if (endDate < startDate)
        return ERROR_BAD_ARGUMENTS;

    COleDateTime dtS(startDate);
    COleDateTime dtE(endDate);
    COleDateTime dt;
    LONG diff = 0;

    if (dtE.GetDay() < dtS.GetDay())
    {
        if (dtS.GetMonth() < 12)
            dt = COleDateTime(dtS.GetYear(), dtS.GetMonth()+1, 1, 0, 0, 0);
        else
            dt = COleDateTime(dtS.GetYear()+1, 1, 1, 0, 0, 0);
        COleDateTimeSpan dtspan = dt - dtS;
        diff = dtspan.GetDays() + dtE.GetDay() - 1;
    }
    else
    {
        diff = dtE.GetDay() - dtS.GetDay();
    }

    *pVal = diff;
    return S_OK;
}

Και ο αντίστοιχος κώδικας σε C#

public class DMYDiff
{
    public static int DMYDays(DateTime startDate, DateTime endDate)
    {
        if (endDate < startDate)
        {
            throw new ArgumentException("Η endDate δεν μπορεί να είναι προγενέστερη της startDate", "endDate");
        }

        int diff = endDate.Year - startDate.Year;
        if (diff > 0)
        {
	        if (endDate.Month < startDate.Month)
		        --diff;
	        else if ((endDate.Month < startDate.Month) && (endDate.Day < startDate.Day))
		        --diff;
        }

        return diff;
    }

    public static int DMYMonths(DateTime startDate, DateTime endDate)
    {
        if (endDate < startDate)
        {
            throw new ArgumentException("Η endDate δεν μπορεί να είναι προγενέστερη της startDate", "endDate");
        }

        int diff = endDate.Month - startDate.Month;

        if (endDate.Day < startDate.Day)
            --diff;
        if (diff < 0)
            diff += 12;

        return diff;
    }

    public static int DMYYears(DateTime startDate, DateTime endDate)
    {
        if (endDate < startDate)
        {
            throw new ArgumentException("Η endDate δεν μπορεί να είναι προγενέστερη της startDate", "endDate");
        }
        DateTime dt;
        int diff = 0;

        if (endDate.Day < startDate.Day)
        {
            if (startDate.Month < 12)
                dt = new DateTime(startDate.Year, startDate.Month + 1, 1, 0, 0, 0);
            else
                dt = new DateTime(startDate.Year + 1, 1, 1, 0, 0, 0);
            TimeSpan startDatepan = dt - startDate;
            diff = startDatepan.Days + endDate.Day - 1;
        }
        else
        {
            diff = endDate.Day - startDate.Day;
        }

        return diff;
    }

}

Κατεβάστε τον κώδικα σε C# μαζί με το dll, ή το ενημερωμένο αρχείο των utilities (DVAUtils.dll) που εξάγει το σχετικό DVA.DateDiff COM Object (πέρα των άλλων που έχουν υλοποιηθεί παλαιότερα).

2 Comments

  1. Μετά από αρκετές ημέρες και μήνες αλλά όχι έτη (μην το παρακάνουμε κι όλας), ξανα-έπιασα τον κώδικα για να γίνει php extension module, και με την ευκαιρία διορθώθηκε και ένα bug.

    Οποιος ενδιαφέρεται…

  2. Στο excel θα μπορούσε :~ να γίνει η αντίστοιχη διαδικασία με τη χρήση των ακόλουθων συναρτήσεων (θεωρώντας ότι στο κελί A1 είναι η αρχική ημερομηνία και στο B1 η τελική):
    Για τις ημέρες: =DATEDIF($A1;$B1;"MD")
    Για τους μήνες: =DATEDIF($A1;$B1;"YM")
    Για τα έτη: =DATEDIF($A1;$B1;"Y")

    Βέβαια δεν είμαι και τόσο σίγουρος ότι η function του excel δουλεύει εντελώς σωστά, γιατί δίνοντας σαν αρχική ημερομηνία στο Α1 το 31/1/1992 και σαν τελική στο Β1 το 20/3/1993, τα αποτελέσματα των συναρτήσεων του excel είναι 1 έτος, 1 μήνας και 17 ημέρες. Εγώ τα υπολογίζω σαν 1 έτος, 1 μήνα και 20 ημέρες.