在 C++ 中比较 2 个日期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13787702/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Comparing 2 dates in c++
提问by David Faizulaev
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\MM\YYYY
我想知道 C++ 中是否有任何相对简单和短日期的比较函数。我的日期类型为char*
,格式如下:DD\MM\YYYY
Thanks.
谢谢。
回答by Potatoswatter
Parsing is usually done on streams, not strings, but you can use a stringstream
.
解析通常在流上完成,而不是在字符串上完成,但您可以使用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.
注意,std::get_time
在 C++11 中是新的。它是根据 定义的strptime
,它来自 POSIX 但不是 C99 标准的一部分。strptime
如果 C++11 库不可用,您可以使用。如果你很勇敢,你也可以使用std::time_get
facet……虽然它很丑。
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.
如果您不想知道除更早日期以外的任何日期,您可以使用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 );
}
回答by Olaf Dietsche
If this is really a fixed format, you can do it with simple C string comparison
如果这确实是固定格式,则可以通过简单的 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);
}
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
.
这就像strncmp
. 它返回一个小于 0 的值,如果d1
早于d2
,如果两者是相同的日期,则返回 0,如果d1
是晚于,则返回大于 0 的值d2
。
Another approach would be to convert it with strptime
and mktime
to time_t
and compare these with difftime
另一种方法是将其与转换strptime
,并mktime
以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);
回答by johnnycrash
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.
一个有效的解决方案怎么样?如果忽略斜线,则固定大小的日期只需要 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;
}
output
输出
-1
1
-1
1
-1
1
回答by eeeeasy
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.
您可以使用 sscanf 和 sprintf 轻松完成。如果您习惯了printf
,scanf
那么这很容易理解,您可以轻松地将其调整到其他情况。没有秘密的魔法函数调用。
#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);
}