时间戳转日期的算法(C语言实现)

1、算法

时间是有周期规律的,4年一个周期(平年、平年、平年、闰年)共计1461天。Windows上C库函数time(NULL)返回的是从1970年1月1日以来的毫秒数,我们最后算出来的年数一定要加上这个基数1970。总的天数除以1461就可以知道经历了多少个周期;总的天数对1461取余数就可以知道剩余的不足一个周期的天数,对这个余数进行判断也就可以得到月份和日了。

当然了,C语言库函数:localtime就可以获得一个时间戳对应的具体日期了,这里 主要说的是实现的一种算法。
2、C语言代码实现

    int nTime = time(NULL);//得到当前系统时间
        int nDays = nTime/DAYMS + 1;    //time函数获取的是从1970年以来的毫秒数,因此需要先得到天数
        int nYear4 = nDays/FOURYEARS;    //得到从1970年以来的周期(4年)的次数
        int nRemain = nDays%FOURYEARS;    //得到不足一个周期的天数
        int nDesYear = 1970 + nYear4*4;
        int nDesMonth = 0, nDesDay = 0;
        bool bLeapYear = false;
        if ( nRemain<365 )//一个周期内,第一年
        {//平年
            
        }
        else if ( nRemain<(365+365) )//一个周期内,第二年
        {//平年
            nDesYear += 1;
            nRemain -= 365;
        }
        else if ( nRemain<(365+365+365) )//一个周期内,第三年
        {//平年
            nDesYear += 2;
            nRemain -= (365+365);
        }
        else//一个周期内,第四年,这一年是闰年
        {//润年
            nDesYear += 3;
            nRemain -= (365+365+365);
            bLeapYear = true;
        }
        GetMonthAndDay(nRemain, nDesMonth, nDesDay, bLeapYear);


计算月份和日期的函数:

    static const int MON1[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};    //平年
    static const int MON2[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};    //闰年
    static const int FOURYEARS = (366 + 365 +365 +365);    //每个四年的总天数
    static const int DAYMS = 24*3600;    //每天的毫秒数
     
    void GetMonthAndDay(int nDays, int& nMonth, int& nDay, bool IsLeapYear)
    {
        int *pMonths = IsLeapYear?MON2:MON1;
        //循环减去12个月中每个月的天数,直到剩余天数小于等于0,就找到了对应的月份
        for ( int i=0; i<12; ++i )
        {
            int nTemp = nDays - pMonths[i];
            if ( nTemp<=0 )
            {
                nMonth = i+1;
                if ( nTemp == 0 )//表示刚好是这个月的最后一天,那么天数就是这个月的总天数了
                    nDay = pMonths[i];
                else
                    nDay = nDays;
                break;
            }
            nDays = nTemp;
        }
    }


3、附上C语言库函数的实现

    <pre name="code" class="cpp">/***
    *errno_t _gmtime32_s(ptm, timp) - convert *timp to a structure (UTC)
    *
    *Purpose:
    *       Converts the calendar time value, in 32 bit internal format, to
    *       broken-down time (tm structure) with the corresponding UTC time.
    *
    *Entry:
    *       const time_t *timp - pointer to time_t value to convert
    *
    *Exit:
    *       errno_t = 0 success
    *                 tm members filled-in
    *       errno_t = non zero
    *                 tm members initialized to -1 if ptm != NULL
    *
    *Exceptions:
    *
    *******************************************************************************/
     
    errno_t __cdecl _gmtime32_s (
            struct tm *ptm,
            const __time32_t *timp
            )
    {
            __time32_t caltim;/* = *timp; *//* calendar time to convert */
            int islpyr = 0;                 /* is-current-year-a-leap-year flag */
            REG1 int tmptim;
            REG3 int *mdays;                /* pointer to days or lpdays */
            struct tm *ptb = ptm;
     
            _VALIDATE_RETURN_ERRCODE( ( ptm != NULL ), EINVAL )
            memset( ptm, 0xff, sizeof( struct tm ) );
     
            _VALIDATE_RETURN_ERRCODE( ( timp != NULL ), EINVAL )
     
            caltim = *timp;
            _VALIDATE_RETURN_ERRCODE_NOEXC( ( caltim >=  _MIN_LOCAL_TIME ), EINVAL )
     
            /*
             * Determine years since 1970. First, identify the four-year interval
             * since this makes handling leap-years easy (note that 2000 IS a
             * leap year and 2100 is out-of-range).
             */
            tmptim = (int)(caltim / _FOUR_YEAR_SEC);
            caltim -= ((__time32_t)tmptim * _FOUR_YEAR_SEC);
     
            /*
             * Determine which year of the interval
             */
            tmptim = (tmptim * 4) + 70;         /* 1970, 1974, 1978,...,etc. */
     
            if ( caltim >= _YEAR_SEC ) {
     
                tmptim++;                       /* 1971, 1975, 1979,...,etc. */
                caltim -= _YEAR_SEC;
     
                if ( caltim >= _YEAR_SEC ) {
     
                    tmptim++;                   /* 1972, 1976, 1980,...,etc. */
                    caltim -= _YEAR_SEC;
     
                    /*
                     * Note, it takes 366 days-worth of seconds to get past a leap
                     * year.
                     */
                    if ( caltim >= (_YEAR_SEC + _DAY_SEC) ) {
     
                            tmptim++;           /* 1973, 1977, 1981,...,etc. */
                            caltim -= (_YEAR_SEC + _DAY_SEC);
                    }
                    else {
                            /*
                             * In a leap year after all, set the flag.
                             */
                            islpyr++;
                    }
                }
            }
     
            /*
             * tmptim now holds the value for tm_year. caltim now holds the
             * number of elapsed seconds since the beginning of that year.
             */
            ptb->tm_year = tmptim;
     
            /*
             * Determine days since January 1 (0 - 365). This is the tm_yday value.
             * Leave caltim with number of elapsed seconds in that day.
             */
            ptb->tm_yday = (int)(caltim / _DAY_SEC);
            caltim -= (__time32_t)(ptb->tm_yday) * _DAY_SEC;
     
            /*
             * Determine months since January (0 - 11) and day of month (1 - 31)
             */
            if ( islpyr )
                mdays = _lpdays;
            else
                mdays = _days;
     
     
            for ( tmptim = 1 ; mdays[tmptim] < ptb->tm_yday ; tmptim++ ) ;
     
            ptb->tm_mon = --tmptim;
     
            ptb->tm_mday = ptb->tm_yday - mdays[tmptim];
     
            /*
             * Determine days since Sunday (0 - 6)
             */
            ptb->tm_wday = ((int)(*timp / _DAY_SEC) + _BASE_DOW) % 7;
     
            /*
             *  Determine hours since midnight (0 - 23), minutes after the hour
             *  (0 - 59), and seconds after the minute (0 - 59).
             */
            ptb->tm_hour = (int)(caltim / 3600);
            caltim -= (__time32_t)ptb->tm_hour * 3600L;
     
            ptb->tm_min = (int)(caltim / 60);
            ptb->tm_sec = (int)(caltim - (ptb->tm_min) * 60);
     
            ptb->tm_isdst = 0;
            return 0;
     
    }
---------------------  

原文:https://blog.csdn.net/mfcing/article/details/48438421  
 

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值