Comparing 2 dates in c++

后端 未结 4 2091
独厮守ぢ
独厮守ぢ 2020-12-17 02:43

I was wondering if there is any relatively easy and short date comparison functions in C++. My dates are of type char*, and have the following format: DD

相关标签:
4条回答
  • 2020-12-17 02:51

    How about an efficient solution? Your fixed size dates only require 8 chars if you ignore the slashes. So with a little shifting and byte swapping you can compare them as 64 bit ints. This is faster than comparing as strings.

    using std::cout;
    using std::endl;
    typedef unsigned __int16 U2;
    typedef unsigned __int32 U4;
    typedef unsigned __int64 U8;
    #define bswap2 _byteswap_ushort
    #define bswap4 _byteswap_ulong
    #define bswap8 _byteswap_uint64
    
    const int YYYYMMDD = 0;
    const int YYYY_MM_DD = 1;
    const int DDMMYYYY = 2;
    const int DD_MM_YYYY = 3;
    
    // compiler will optimize the if's out.
    template <int FMT>
    U8 DateToInt(char* sz) {
        if (FMT == YYYYMMDD) {
            return bswap8(*(U8*)sz);
        }
        if (FMT == YYYY_MM_DD) {
            U4 y = *(U4*)sz, m = *(U2*)(sz + 5), d = *(U2*)(sz + 8);
            return ((U8)bswap4(y) << 32) | (bswap2(m) << 16) | bswap2(d);
        }
        if (FMT == DD_MM_YYYY) {
            U4 y = *(U4*)(sz + 6), m = *(U2*)(sz + 3), d = *(U2*)sz;
            return ((U8)bswap4(y) << 32) | (bswap2(m) << 16) | bswap2(d);
        }
    }
    
    template<int FMT1, int FMT2 = FMT1>
    __int64 CompareDate(char* sz1, char* sz2) {
        return DateToInt<FMT1>(sz1) - DateToInt<FMT2>(sz2);
    }
    
    void main() {
        cout << CompareDate<YYYYMMDD>("20151025", "20151026") << endl;
        cout << CompareDate<YYYYMMDD>("20151025", "20151024") << endl;
        cout << CompareDate<YYYYMMDD, YYYY_MM_DD>("20151025", "2015/10/26") << endl;
        cout << CompareDate<YYYYMMDD, YYYY_MM_DD>("20151025", "2015/10/24") << endl;
        cout << CompareDate<YYYYMMDD, DD_MM_YYYY>("20151025", "26/10/2015") << endl;
        cout << CompareDate<YYYYMMDD, DD_MM_YYYY>("20151025", "24/10/2015") << endl;
    }
    

    output

    -1
    1
    -1
    1
    -1
    1
    
    0 讨论(0)
  • 2020-12-17 02:56

    Parsing is usually done on streams, not strings, but you can use a stringstream.

    std::istringstream date_s( "04\\10\\1984" );
    struct tm date_c;
    date_s >> std::get_time( &date_c, "%d\\%m\\%Y" );
    std::time_t seconds = std::mktime( & date_c );
    

    Now you can compare seconds using < to determine which was earlier.

    Note, std::get_time is new in C++11. It is defined in terms of strptime, which is from POSIX but not part of the C99 standard. You can use strptime if a C++11 library is not available. If you're brave, you can also use the std::time_get facet… it's ugly though.

    If you don't want to know anything about the dates other than which is earlier, you can use std::lexicographical_compare. It would be a one-liner but the function name is so long.

    // return true if the date string at lhs is earlier than rhs
    bool date_less_ddmmyyyy( char const *lhs, char const *rhs ) {
        // compare year
        if ( std::lexicographical_compare( lhs + 6, lhs + 10, rhs + 6, rhs + 10 ) )
            return true;
        if ( ! std::equal( lhs + 6, lhs + 10, rhs + 6 ) )
            return false;
        // if years equal, compare month
        if ( std::lexicographical_compare( lhs + 3, lhs + 5, rhs + 3, rhs + 5 ) )
            return true;
        if ( ! std::equal( lhs + 3, lhs + 5, rhs + 3 ) )
            return false;
        // if months equal, compare days
        return std::lexicographical_compare( lhs, lhs + 2, rhs, rhs+2 );
    }
    

    See also how to convert datetime to unix timestamp in c? .

    0 讨论(0)
  • 2020-12-17 03:04

    If this is really a fixed format, you can do it with simple C string comparison

    int date_cmp(const char *d1, const char *d2)
    {
        int rc;
        // compare years
        rc = strncmp(d1 + 6, d2 + 6, 4);
        if (rc != 0)
            return rc;
    
        // compare months
        rc = strncmp(d1 + 3, d2 + 3, 2);
        if (rc != 0)
            return rc;
    
        // compare days
        return strncmp(d1, d2, 2);
    }
    

    This works like strncmp. It returns a value less than 0, if d1 is earlier than d2, 0 if both are the same date, and a value greater than 0, if d1 is later than d2.

    Another approach would be to convert it with strptime and mktime to time_t and compare these with difftime

    struct tm tm;
    time_t t1, t2;
    strptime(d1, "%d\\%m\\%Y", &tm);
    t1 = mktime(&tm);
    // do the same with d2
    double diff = difftime(t1, t2);
    
    0 讨论(0)
  • 2020-12-17 03:08

    You need to extract the numeric data from the string. Worst case scenario is a bunch of loops and string to integer conversion functions.

    You can do it easily with sscanf and sprintf. If you're used to printf and scanf then this is simple to understand, and you can easily adapt it to other cases. There are no secret magic function calls.

    #include <stdio.h>
    void main()
    {
        char* date1 = "9\\12\\2012"; 
        char* date2 = "6\\11\\2013"; 
    
        int day1,month1,year1;
        int day2,month2,year2;
    
        sscanf(date1,"%d\\%d\\%d",&day1,&month1,&year1); //reads the numbers
        sscanf(date2,"%d\\%d\\%d",&day2,&month2,&year2); //from the string
    
        if (year1<year2 || month1<month2 || day1<day2) //compares 2 dates
        {
            printf("date1 < date2\n");
        }
        else
        {
            printf("date1 >= date2\n");
        }
    
        char newdate[15];
    
        sprintf(newdate,"%d\\%d\\%d",13,2,1998); //make a date string from numbers
        printf("%s\n",newdate);
    }
    
    0 讨论(0)
提交回复
热议问题