Comparing two dates in C ++

I was wondering if in C ++ there are relatively simple and short date comparison functions. My dates are of type char* and have the following format: DD\MM\YYYY

Thanks.

+4
source share
4 answers

Parsing is usually done in streams, not in strings, but you can use 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 what happened before.

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

If you do not want to know anything about dates other than the previous ones, you can use std::lexicographical_compare . It will be single-line, but the function name will be 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 ); } 

See also how to convert date and time in unix timestamp to c? .

+6
source

If this is a really fixed format, you can do this with a simple string 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 earlier than d2 , 0 if both have the same date, and a value is greater than 0 if d1 less than d2 .

Another approach would be to convert it using strptime and mktime to time_t and compare them 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); 
+2
source

You need to extract the numeric data from the string. In the worst case scenario, it is a collection of loops and functions for converting integers to integers.

You can do this easily with sscanf and sprintf. If you are used to printf and scanf then this is easy to understand, and you can easily adapt it to other cases. 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); } 
+1
source

How about an effective solution? Fixed fixed dates require only 8 characters if you ignore slashes. Thus, with a little switching and byte, you can compare them as 64-bit ints. This is faster than string comparison.

 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 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 
+1
source

All Articles