6

我想知道 C++ 中是否有任何相对简单和简短的日期比较函数。我的日期类型为char*,格式如下:DD\MM\YYYY

谢谢。

4

4 回答 4

6

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? .

于 2012-12-09T13:41:42.967 回答
2

如果这真的是一个固定格式,你可以通过简单的 C 字符串比较来做到这一点

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);
}

这就像strncmp. d1如果早于,则返回小于 0 的值d2,如果两者是相同日期则返回 0 ,如果d1晚于则返回大于 0 的值d2

另一种方法是将其转换为strptimeand mktimetotime_t并将它们与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);
于 2012-12-09T13:51:42.200 回答
1

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);
}
于 2012-12-09T13:47:53.057 回答
1

一个有效的解决方案怎么样?如果您忽略斜线,您的固定大小日期只需要 8 个字符。因此,通过一些移位和字节交换,您可以将它们与 64 位整数进行比较。这比作为字符串进行比较要快。

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;
}

输出

-1
1
-1
1
-1
1
于 2015-10-31T21:01:43.347 回答