分享

[求助]怎样将1970年1月1日0时以来经过的秒数转换为日期,不用库函数!谢谢!

 戴维图书馆 2015-04-05

[求助]怎样将1970年1月1日0时以来经过的秒数转换为日期,不用库函数!谢谢!

将当前日期转换成距1970年1月1日0时经过的秒数的算法在linux的源码中有,但是将经过的秒数转换为日期的算法则没有找到!
各位大大有什么比较好的算法吗?谢谢!
昵称: dengxiaojun1983  时间: 2010-07-23 08:56:00
秒数除以86400变为经过的天数,然后根据平闰年每次减去365或366,确定年份,然后是具体的月和日……
昵称: daybreakcx  时间: 2010-07-23 08:59:00


QUOTE:
将当前日期转换成距1970年1月1日0时经过的秒数的算法在linux的源码中有,但是将经过的秒数转换为日期的算法 ...
dengxiaojun1983 发表于 2010-07-23 08:56

  1. long rtt_mktime(DATE_TIME time, long timezone /*= 8*/)
  2. {
  3.     long res;
  4.        
  5.     // 1..12 -> 11,12,1..10, Puts Feb last since it has leap day
  6.     if (time.month <= 2)
  7.         {
  8.         time.month += 10;
  9.         time.year -= 1;
  10.     }
  11.     else
  12.         {
  13.         time.month -= 2;
  14.     }
  15.        
  16.     /**//*
  17.                 // Calculate how much days from 1970 to today
  18.                 res = 59;                            //31@0001-January and 28@0001-February
  19.                 res += (time.year - 1) * 365;        //at least 365 days one year
  20.                 res += time.year / 4 - time.year / 100 + time.year / 400;    //leap years from 0001
  21.                 res += 367 * time.month / 12 - 30;    //days from March(0.5/7<=slope<0.5/5)
  22.                 res += time.day - 1;                //days
  23.                 res -= 719162;                        //days from 0001-1-1 to 1970-1-1
  24.                 // Calculate how much seconds
  25.                 res = ( (res * 24 + time.hour) * 60 + time.minute) * 60 + time.second;
  26.     */
  27.     /**////*
  28.     res = (long)(time.year/4 - time.year/100 + time.year/400) +
  29.                 367*time.month/12 + time.day +
  30.                 time.year*365 - 719499;
  31.     res = ((res*24 + time.hour        // now have hours
  32.                 )*60 + time.minute            // now have minutes
  33.                 )*60 + time.second;            // finally seconds
  34.     //*/
  35.        
  36.         res -= timezone * 60 * 60;
  37.     return res;
  38. }

  39. int rtt_isleap(unsigned short year)
  40. {
  41.         return ((year%4==0)&&(year%100!=0)||(year%400==0));
  42. }

  43. void rtt_localtime(long res, DATE_TIME *time, long timezone /*= 8*/)
  44. {
  45.     const int monthLengths[2][13] = {
  46.         { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
  47.                 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
  48.     };
  49.     const int yearLengths[2] = { 365, 366 };
  50.     int year;
  51.     int month;
  52.     int minMonth;
  53.     int maxMonth;
  54.    
  55.     int days;
  56.     int clock;
  57.     int isLeap;
  58.    
  59.         res += timezone*60*60;

  60.     days = res / 86400;
  61.     clock = res % 86400;
  62.     if(clock < 0)
  63.         {
  64.         clock += 86400;
  65.         days -= 1;
  66.     }
  67.    
  68.     /**/////////////////////////////////////////////////////////////////////////////
  69.     // Calcaulate year, 11323=0x3A4FC880/86400; 13879=0x47798280/86400
  70.     /**////////////////////////////////////////////////////////////////////////////   
  71.     if(days >= 0)
  72.         {
  73.         year = days/366;
  74.         days -= year*365 + (year+1)/4 - (year+69)/100 + (year+369)/400;
  75.         
  76.         for(time->year = year + 1970; ; time->year++)
  77.                 {
  78.                         isLeap = rtt_isleap(time->year);
  79.                         if(days < yearLengths[isLeap])
  80.                         {
  81.                                 break;
  82.                         }
  83.                         days -= yearLengths[isLeap];
  84.         }
  85.     }
  86.     else
  87.         {
  88.         year = days/366;
  89.         days -= year*365 + (year-2)/4 - (year-30)/100 + (year-30)/400;
  90.         
  91.         for(time->year = year + 1970 - 1; ; time->year--)
  92.                 {
  93.             isLeap = false;//rtt_isleap(time->year);
  94.             days += yearLengths[isLeap];
  95.             
  96.             if(days >= 0)
  97.                         {
  98.                 break;
  99.             }
  100.         }
  101.     }   
  102.    
  103.     /**///////////////////////////////////////////////////////////////////////////
  104.     // compute month and day, use the half search save time
  105.     /**////////////////////////////////////////////////////////////////////////////
  106.     minMonth = 0;
  107.     maxMonth = 12;
  108.     for(month = 5; month < 12 && month > 0; month = (minMonth + maxMonth) / 2)
  109.         {
  110.         // days between monthLengths[month]<=days<monthLengths[month+1]
  111.         if(days < monthLengths[isLeap][month])    //too big
  112.                 {
  113.             maxMonth = month;
  114.         }
  115.         else if(days >= monthLengths[isLeap][month + 1])    //too small
  116.                 {
  117.             minMonth = month;
  118.         }
  119.         else    //so it is
  120.                 {
  121.             break;
  122.         }
  123.     }
  124.     days -= monthLengths[isLeap][month];
  125.     time->month = month + 1;
  126.    
  127.     time->day = days + 1;
  128.    
  129.    
  130.     /**///////////////////////////////////////////////////////////////////////////
  131.     // Calcaulate hour minute and second
  132.     /**///////////////////////////////////////////////////////////////////////////
  133.     time->hour = clock / 3600;        //3600s one hour
  134.     clock = clock % 3600;
  135.     time->minute = clock / 60;        //60s one minute
  136.     time->second = clock % 60;        //ms
  137. }


  138. /*========================================================================
  139. * Function name        : gmt_convert_local
  140. * Description            : 将格林尼治时间转换为本地时间
  141. * Return type                : bool
  142. * Argument         :
  143. *                  : const char* gmt 格林尼治时间 20091105082121
  144. *                  : char* local        20091105/162121
  145. ========================================================================*/
  146. bool gmt_convert_local(const char* gmt, char* local)
  147. {
  148.         if ( strlen(gmt) != 14 )
  149.                 return false;
  150.         //格林尼治时间转换为本地时间
  151.         char year[5];
  152.         char month[3];
  153.         char day[3];
  154.         char hour[3];
  155.         char minute[3];
  156.         char second[3];
  157.        
  158.         sscanf(gmt, "%4s%2s%2s%2s%2s%2s", year, month, day, hour, minute, second);
  159.        
  160.         DATE_TIME utc_time;
  161.         DATE_TIME local_time;
  162.        
  163.         utc_time.year = atoi(year);
  164.         utc_time.month = atoi(month);
  165.         utc_time.day = atoi(day);
  166.         utc_time.hour = atoi(hour);
  167.         utc_time.minute = atoi(minute);
  168.         utc_time.second = atoi(second);
  169.        
  170.         long time_second = rtt_mktime(utc_time, 0);//utc时间, 0 时区
  171.        
  172.         rtt_localtime(time_second, &local_time, 8);
  173.        
  174.         sprintf(local, "%04d%02d%02d/%02d%02d%02d", local_time.year, local_time.month, local_time.day,
  175.                  local_time.hour, local_time.minute, local_time.second);

  176.         return true;
  177. }
复制代码
昵称: rain_fish  时间: 2010-07-23 09:01:00
呵呵,好像不是你的要求
昵称: rain_fish  时间: 2010-07-23 09:02:00
为啥不要库函数?
昵称: hellioncu  时间: 2010-07-23 09:03:00
  1. #include <stdio.h>
  2. int dm[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  3. int year, month, n, dy;
  4. int leap(int year)
  5. {
  6.         return year % 400 == 0 || year % 4 == 0 && year % 100;
  7. }
  8. int main()
  9. {
  10.         scanf("%d", &n);
  11.         n /= 86400;
  12.         ++n;
  13.         for (year = 1970; ; ++year) {
  14.                 dy = 365 + leap(year);
  15.                 if (n <= dy)
  16.                         break;
  17.                 else
  18.                         n -= dy;
  19.         }
  20.         dm[2] = 28 + leap(year);
  21.         for (month = 1; ; ++month)
  22.                 if (n <= dm[month])
  23.                         break;
  24.                 else
  25.                         n -= dm[month];
  26.         printf("%04d-%02d-%02d\n", year, month, n);
  27.         return 0;
  28. }
复制代码
贴一个试一下
昵称: daybreakcx  时间: 2010-07-23 09:26:00


QUOTE:
为啥不要库函数?
hellioncu 发表于 2010-07-23 09:03




    因为是一个嵌入式系统中,没有使用linux,使用RTC,必须自己实现转换!
昵称: dengxiaojun1983  时间: 2010-07-23 09:40:00


QUOTE:
rain_fish 发表于 2010-07-23 09:01




    将从1970年1月1日0时以来经过的秒数,我改写了的是long kernel_mktime(struct tm * tm)函数实现的!你采用的算法很经典!貌似采用高斯算法?
反过来的,我好好看看,将其移植过来,谢谢!
昵称: dengxiaojun1983  时间: 2010-07-23 09:46:00

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多