简体   繁体   中英

Safe way to compare dates (time_t)

I was trying to write a portable function that checks if a date is inside a range I wrote this implementation but doesn't work:

/**
 * @brief teIsDateInRange checks if a date is inside a range of dates
 *        teIsDateRange checks if date is in [firstDate, endDate]
 * @param firstDate first date of the range
 * @param lastDate last date of the range
 * @param date date to check
 * @return 0 if the date is in the range, 1 if date is greater then lastDate or
 *         -1 if date is less than firstDate
 */
TMEXT_API int TMEXT_CALL teIsDateInRange( time_t firstDate, time_t lastDate, time_t date )
{
    const auto diff1 = std::difftime( firstDate, date );

    if ( diff1 > 0.0 ) return -1;
    if ( diff1 == 0.0 ) return 0;

    // we are sure that date is greater then firstDate now check upper range
    const auto diff2 = std::difftime( date, lastDate );
    if ( diff2 >= 0.0 ) return 0;
    else return 1;
}

I've wrote a simple test suite but test fails

// main.cpp
#define BOOST_TEST_MODULE timeext_test_unit
#include <timeext/timeext.h>            // function where is defined teIsDateInRange

#include <utility/diagnostic.h>
// stop warnings on mingw with boost 1.55.0
GCC_DIAG_STOP
GCC_DIAG_OFF(unused-local-typedefs)
#include <boost/test/included/unit_test.hpp>
GCC_DIAG_START

#include <iostream>
using namespace std;


BOOST_AUTO_TEST_SUITE( test_suite1 )

BOOST_AUTO_TEST_CASE( test_case1 )
{
    const time_t first = time( nullptr );
    const time_t last = first + 500;
    const time_t d1 = first - 50;
    const time_t d2 = first + 40;
    const time_t d3 = first + 600;

    const auto r1 = teIsDateInRange( first, last, d1 );
    const auto r2 = teIsDateInRange( first, last, d2 );
    const auto r3 = teIsDateInRange( first, last, d3 );

    BOOST_REQUIRE( r1 == -1 );
    BOOST_REQUIRE( r2 ==  0 );      // <--- line 30: fail
    BOOST_REQUIRE( r3 ==  1 );
}

BOOST_AUTO_TEST_SUITE_END()

This is the output of the test suite:

Running 1 test case...
main.cpp(30): fatal error in "test_case1": critical check r2 == 0 failed

*** 1 failure detected in test suite "timeext_test_unit"

A way to pass test is reimplement the function in this way but is not portable:

TMEXT_API int TMEXT_CALL teIsDateInRange( time_t firstDate, time_t lastDate, time_t date )
{
    if ( date < firstDate )
        return -1;

    if ( date > lastDate )
        return 1;

    return 0;
}

Does someone know a portable way to check if a date is inside a range?

Another question the declaration of difftime is the following: difftime声明的另一个问题如下:

double difftime (time_t end, time_t beginning);

This seems to presume that end is bigger then beggining. In my situation I don't know if end is bigger than beggining.

Here you check if date > lastDate and in that case you return 0:

// we are sure that date is greater then firstDate now check upper range
const auto diff2 = std::difftime( date, lastDate );
if ( diff2 >= 0.0 ) return 0;

You should return 0 if date < lastDate:

// we are sure that date is greater then firstDate now check upper range
const auto diff2 = std::difftime( date, lastDate );
if ( diff2 <= 0.0 ) return 0;

Your second test returns 1 if date < lastDate . You want to return 1 if date > lastDate , ie

const auto diff2 = std::difftime( date, lastDate );
if ( diff2 > 0.0 ) return 1;
else return 0;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM