免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 14052 | 回复: 11
打印 上一主题 下一主题

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

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-07-23 08:56 |只看该作者 |倒序浏览
将当前日期转换成距1970年1月1日0时经过的秒数的算法在linux的源码中有,但是将经过的秒数转换为日期的算法则没有找到!
各位大大有什么比较好的算法吗?谢谢!

论坛徽章:
0
2 [报告]
发表于 2010-07-23 08:59 |只看该作者
秒数除以86400变为经过的天数,然后根据平闰年每次减去365或366,确定年份,然后是具体的月和日……

论坛徽章:
0
3 [报告]
发表于 2010-07-23 09:01 |只看该作者
将当前日期转换成距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. }
复制代码

论坛徽章:
0
4 [报告]
发表于 2010-07-23 09:02 |只看该作者
呵呵,好像不是你的要求

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
5 [报告]
发表于 2010-07-23 09:03 |只看该作者
为啥不要库函数?

论坛徽章:
0
6 [报告]
发表于 2010-07-23 09:26 |只看该作者
  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. }
复制代码
贴一个试一下

论坛徽章:
0
7 [报告]
发表于 2010-07-23 09:40 |只看该作者
为啥不要库函数?
hellioncu 发表于 2010-07-23 09:03



    因为是一个嵌入式系统中,没有使用linux,使用RTC,必须自己实现转换!

论坛徽章:
0
8 [报告]
发表于 2010-07-23 09:46 |只看该作者
rain_fish 发表于 2010-07-23 09:01



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

论坛徽章:
0
9 [报告]
发表于 2010-07-23 14:31 |只看该作者
将从1970年1月1日0时以来经过的秒数,我改写了的是long kernel_mktime(struct tm * tm)函数实现的 ...
dengxiaojun1983 发表于 2010-07-23 09:46



    客气啦。。

论坛徽章:
0
10 [报告]
发表于 2010-07-23 14:47 |只看该作者
为什么不用库函数?自己写太麻烦了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP