文章目錄

在项目中很多时候需要判断两个时间是否是同一天,例如用户每天都能领某种福利一次且只能领取一次,这时候当用户领取福利的时就需要判断用户上次领取的时间与当前时间是不是同一天,不是同一天的话可以领取,否则不能领取。

一般来讲我会用time(NULL)来获取用户当前领取时间,它返回的是一个整数,代表从CUT(Coordinated Universal Time 格林威治时间)时间1970年1月1日00:00:00到当前时刻的秒数,正因为它是一个整数所以这样便于存储和比较。假如两个时间分别是oldtime和newtime,他们都是用time(NULL)得到的整数时间,我们想判断他们是否是同一天只需要分别求得他们的天数,然后判断是不是相等即可,即这样:

IsANewDay gettimeofday

#define SECONDSOFONEDAY (24*60*60)  
bool IsANewDay(time_t tOldTime,  time_t tNewTime)  
{  
    int iDayOld = static_cast<int>(tOldTime/SECONDSOFONEDAY);  
    int iDayNew = static_cast<int>(tNewTime/SECONDSOFONEDAY);  
    if(iDayNew > iDayOld)  
    {  
        return true;  
    }  
    else  
    {  
        return false;  
    }  
}

理论上来讲这样判断就可以了,但是仔细分析会发现这样的判断是以格林威治时间为标准的,也就是说计算的是从格林威治时间1970年1月1日00:00:00以来的第几天,但是我们实际需要计算的是对于我们当前时区来讲的第几天,所以直接用上述算法是有问题的。例如我们当前时区的时间是零点,正好是新的一天,但格林威治时间却还没到零点,这就差了一天,所以要修改算法,以当前时区来计算:

#define SECONDSOFONEDAY (24*60*60)  
bool IsANewDay(time_t tOldTime,  time_t tNewTime)  
{  
    struct timezone tvTimeZone;  
    gettimeofday(NULL, &tvTimeZone);  
    int iTimeZoneSeconds = (-tvTimeZone.tz_minuteswest*60);  
    int iDayOld = static_cast<int>((tOldTime+iTimeZoneSeconds)/SECONDSOFONEDAY);  
    int iDayNew = static_cast<int>((tNewTime+iTimeZoneSeconds)/SECONDSOFONEDAY);  
    if(iDayNew > iDayOld)  
    {  
        return true;  
    }  
    else  
    {  
        return false;  
    }  
}

tvTimeZone.tz_minuteswest返回的是当前时区时间与格林威治时间时间差了多少分钟,所以用之前得到的秒数减去与格林威治时间相差的秒数就得到了当前时区对应的秒数,这样再除以一天的秒数就得到了正确的天数。其实有不少情况我们不想以零点来判断是否是新的一天,好比我们把凌晨5点当做分割线,凌晨5点之前是昨天,之后是新的一天,这时候再判断两个时间是不是新的一天又不一样了。其实改动也很小,只需要在原算法中加个偏移量就好了:

#define SECONDSOFONEDAY (24*60*60)  
bool IsANewDay(time_t tOldTime,  time_t tNewTime, int iOffSetTime)  
{  
    struct timezone tvTimeZone;  
    gettimeofday(NULL, &tvTimeZone);  
    int iTimeZoneSeconds = (-tvTimeZone.tz_minuteswest*60);  
    int iDayOld = static_cast<int>((tOldTime+iTimeZoneSeconds-iOffSetTime)/SECONDSOFONEDAY);  
    int iDayNew = static_cast<int>((tNewTime+iTimeZoneSeconds-iOffSetTime)/SECONDSOFONEDAY);  
    if(iDayNew > iDayOld)  
    {  
        return true;  
    }  
    else  
    {  
        return false;  
    }  
}

例如,IsANewDay(oldtime, newtime, 56060)即返回相对于凌晨五点来讲oldtime和newtime是不是新的一天,我们得到的时间本来是相对于格林威治时间1970年1月1日00:00:00的秒数(相对于零点),如果想以凌晨5点为标准的话,我们只需要计算相对于格林威治时间1970年1月1日05:00:00的秒数即可,所以把时间减去offsettime(56060)就好了。

文章目錄