【问题标题】:Comparing 2 dates in c++在 C++ 中比较 2 个日期
【发布时间】:2012-11-27 02:01:28
【问题描述】:

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

谢谢。

【问题讨论】:

  • 相关:stackoverflow.com/questions/1650715/c-standard-date-time-class 。我编写了自己的日期类来进行这些操作。你也可以轻松做到。
  • 还可以查看 C++11 的新 chrono 标头,该标头支持某些日期和时间实用程序。
  • 反斜杠,而不是正斜杠?
  • 格式是必需的吗? ISO 标准日期,YYYY-MM-DD,可以与普通字符串比较进行比较。
  • 是的,这是给定日期的格式,DD\MM\YYYY。

标签: c++


【解决方案1】:

解析通常在流上完成,而不是字符串,但您可以使用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 );

现在您可以使用 < 比较秒数以确定哪个更早。

注意,std::get_time 是 C++11 中的新功能。它是根据strptime 定义的,它来自POSIX,但不是C99 标准的一部分。如果 C++11 库不可用,您可以使用 strptime。如果你够勇敢,你也可以使用std::time_get facet……不过这很难看。

如果您不想知道除较早日期之外的任何日期,您可以使用std::lexicographical_compare。这将是一个单行,但函数名称很长。

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

另见how to convert datetime to unix timestamp in c?

【讨论】:

  • 对于 std::get_time 示例,在 Visual Studio 2013 中,我需要首先将 tm 结构 memset 为零,以使 mktime 工作。例如:memset(&date_c, 0, sizeof(date_c));
【解决方案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 早于d2,则返回小于0 的值,如果两者是同一日期,则返回0,如果d1 晚于d2,则返回大于0 的值。

另一种方法是将其与strptimemktime 转换为time_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);

【讨论】:

    【解决方案3】:

    您需要从字符串中提取数字数据。最坏的情况是一堆循环和字符串到整数的转换函数。

    您可以使用 sscanf 和 sprintf 轻松完成。如果您习惯了printfscanf,那么这很容易理解,您可以轻松地将其适应其他情况。没有秘密的魔法函数调用。

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

    【讨论】:

    • 谢谢,但我在 D\M\Y 之间只有一个 ' \ ' 而不是两个
    • 第二个是转义斜线
    • 我希望没有人使用这个,因为日期比较是错误的。应该是if (year1 != year2) { return year1 &lt; year2; } 等。
    【解决方案4】:

    一个有效的解决方案怎么样?如果您忽略斜线,您的固定大小日期只需要 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
    

    【讨论】:

      猜你喜欢
      • 2014-08-06
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多