mktime很慢就自己去实现一个吧

mktime很慢就自己去实现一个吧

标签(空格分隔): Linux C语言


1. 前言

  • 最近遇到一个转换数据的程序,只是一些内存操作,但是程序表现的巨慢,导致上线之后要天天盯着是否正常。忍不了,就使用gprofiler分析了一波,发现的结果是一个时间转换上十分耗时(占比达到90%多)
  • mktime是用来把字符串时间(YYYYMMDD-HH:MM:SS)转换为unix时间戳的

2. 慢的原因

根据后面自己的测试和前辈说的总结下:

  • 根据我的测试发现,我自己写的函数都是在用户态下的耗时,而mktime的有一半时间是在内核态的耗时。
  • 前辈说:“这个函数有锁的。” 具体未知,有时间去探索下。

3. 自己实现一个

  • 番外:转自漫画:程序员的日常:时间戳和时区的故事 
    1.时间戳:指的就是Unix时间戳(Unix timestamp)。它也被称为Unix时间(Unix time)、POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。因此,严格来说,不管你处在地球上的哪个地方,任意时间点的时间戳都是相同的。这点有利于线上和客户端分布式应用统一追踪时间信息。 
    2.时区:中国时区是东8区 

    时间戳相同的根本原因是因为时区,这么想,时间戳相同,那么我们可以转换自己本地时间的时候就需要一个偏移来,那就是时区的作用了。同样在实现本地时间字符串转换为时间戳的时候,也需要加入时区的偏移来还原时间戳。后面会在代码中说清楚。 
    UTC,GMT等时间参考:时间:UTC时间、GMT时间、本地时间、Unix时间戳

  • 实现 
    参考:“mktime” slow? use custom function. 
    主要实现是使用c语言的 struct tm结构体和时间戳时区关系来计算就好了。 
    代码是参考上面博主的,但是他的代码存在问题,比如时区的处理,还有闰年的处理上,自己实现之后使用脚本测试过一些日期和mktime对比是没有问题的。

上代码如下: 
代码下载:github——str_to_stamp.c

 1 #include <stdio.h>
 2 #include <time.h>
 3
 4 /*字符串时间(YYYYMMDD-HH:MM:mm)转换为struct tm结构*/
 5 void str_to_tm(char *p_time, struct tm* m_tm)
 6 {
 7     if(p_time)
 8     {
 9         sscanf(p_time, "%4d%2d%2d-%d:%d:%d", &m_tm->tm_year,&m_tm->tm_mon,&m_tm->tm_mday,&m_tm->tm_hour,&m_tm->tm_min,&m_tm->tm_sec);
10         m_tm->tm_mon -= 1;
11         m_tm->tm_year -= 1900;
12     printf("%4d%2d%2d-%d:%d:%d\n", m_tm->tm_year,m_tm->tm_mon,m_tm->tm_mday,m_tm->tm_hour,m_tm->tm_min,m_tm->tm_sec);
13     }
14     else
15     {
16         printf("input time is null\n");
17         return ;
18     }
19 }
20
21 /*时间结构转换为时间戳*/
22 time_t time_to_stamp(const struct tm* ltm, int utc_diff)
23 {
24     const int mon_days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
25     long tyears,tdays,leap_years,utc_hrs;
26     int is_leap;
27     int i,ryear;
28
29     //判断闰年
30     ryear = ltm->tm_year + 1900;
31     is_leap = ((ryear%100!=0 && ryear%4==0) || (ryear%400==0) ) ? 1 : 0;
32
33     tyears = ltm->tm_year-70;  //时间戳从1970年开始算起
34     if(ltm->tm_mon < 1 && is_leap==1 )
35     {
36         leap_years = (tyears + 2) / 4 - 1;  //1970年不是闰年,从1972年开始闰年
37                                             //闰年的月份小于1,需要减去一天
38     }
39     else
40     {
41         leap_years = (tyears + 2) / 4 ;
42     }
43
44     tdays = 0;
45     for(i=0; i<ltm->tm_mon; ++i)
46     {
47         tdays += mon_days[i];
48     }
49     tdays += ltm->tm_mday - 1;  //减去今天
50     tdays += tyears * 365 + leap_years;
51     utc_hrs = ltm->tm_hour - utc_diff;   //如上面解释所说,时间戳转换北京时间需要+8,那么这里反转需要-8
52
53     return (tdays * 86400) + (utc_hrs * 3600) + (ltm->tm_min * 60) + ltm->tm_sec;
54 }
55
56 int main(int argc, char **argv)
57 {
58     char *ptime = argv[1];
59     struct tm tt;
60     int ltime = 0;
61     int systime = 0;
62     str_to_tm(ptime,&tt);
63     ltime = time_to_stamp(&tt,8);
64     printf("ltime=%d\n",ltime);
65     return 0;
66 }
时间: 2024-11-10 01:14:21

mktime很慢就自己去实现一个吧的相关文章

教你简单的去运营一个社区论坛

首先运营是个很宽泛的词.往大说,可以上升到运作,管理,这就包括决策,内容,技术,市场,销售.不考虑金钱和远景很大的话,重要级就是先后顺序.(不自信地说,一家之言,具体有待商榷) 在这里,我理解为题主问的是狭义的运营,即针对内容团队.其他因素完全忽略.当然,除非内容端是无可取代性,否则狭义运营再好,也白搭.俗话叫,不怕神一样的对手,就怕……. 回归问题,从内容端入手首先保证三个关键词,稳定,规律,及时.重要性同样是先后顺序. 这里应该会有不同观点,即及时.常关注互联网的人的人回知道这么一句话,唯快

假如正则从来没来过,我们该如何去匹配一个字符串?

正则表达式其实挺难的,对于新手来说就好比一本天书.很多高端大气上档次的教程啊教材啊博客啊一般都是先列出框框条条,再来细讲,先元字符再量词再分组再反向引用.我估计是国人都受到了国外教材的影响,因为这些东西是他们整出来的.对于他们来说思路是很清晰的.老手还好,勉强能吃透.新手你没个几十遍的功夫,门都找不到在哪里.光那些规则,字母意思啊就够你喝一壶的了,你是忘了看,看了忘.(ps:本文针对javascript正则) 假如我们根本就不知道有正则这玩意儿存在,要去匹配一个字母串我们应该怎么做了?让我们也做

去另一个城市工作生活

我主张去另一个城市工作生活的意思是,我们应该至少在两个以上城市长期工作或者生活,而不是只待在一个城市,因为两个不同城市工作和生活的经历,可以让我们对城市生活的共同点和不同点都有更好的认识.生活和工作的本质是怎样的,不同城市的地理.经济.文化差异又会给我们的工作和生活带来如何的不同,这些是很有意思的事情,同时,在不同的城市可以认识不一样的朋友圈,有差异的朋友圈也会带来不一样的认识和感受.尤其不同的城市本身差异越大,这种有价值的感受便越强烈,华南的广州深圳,华东的上海杭州,华中的长沙武汉,西部的成都

怎么去运营一个稳定流量的个人网站

无意间发现这个问题,无意间发现是校友~ 要有稳定的流量来源,首先有一点是要有稳定的原创新内容,刚大概看了一下你的网站,今年的三四月份更新的内容比较多,再之后更新的内容就很少了.至于为什么讲原创呢,搜索引擎对于原创内容的抓取是要高于非原创的,这样网站在搜索引擎的排名也会比较高. 第二点,首页上的内容要放最新的,这是因为让用户进来看的时候一眼就看到这个网站还活着,有人在打理,接下来也会有新的内容,这样才有持续关注的一个动力. 第三点,去掉广告.广告是一个很烦人的东西,尤其你的京东和淘宝的广告,都占据

记录一个python里面很神奇的操作,对一个包含列表的元组进行增量赋值,成功赋值但还报错

记录一个python里面很神奇的操作 今天记录一个很神奇的操作.关于序列的增量赋值.如果你很熟悉增量赋值,你也不妨看下去,我想说的是有关于增量赋值和元组之间一种神奇的操作.来自 <流畅的Python> 一书,让我们更加深入地了解里面的原理 神奇的操作 >>>t = (1,2,[30,40]) >>>t[2] += [50,60] 上面这段代码会出现什么样的情况 a. t会变成(1,2,[30,40,50,60]) b. 因为tuple不支持对它的元素赋值,所

如何用面向对象的思维去封装一个小型轮播图插件

1.面向对象与面向过程 既然说到面向对象的思维,那就免不了要对面向过程的编程思维与面向对象的思维做一番比较. 笔者有 一段时间天真的认为有一个类,然后new一个对象就是面向对象编程了,现在想想还是太naive了呀. 其实面向对象的编程思维和面向过程的编程思维重要的不是对象和过程,而是思维. 比如说在生活中我们要做一道西红柿炒鸡蛋,很多人的第一反应就是西红柿炒鸡蛋第一步.第二步.第三步应该怎么做,每一步放什么调料.然后在做的过程中找每一步需要的调料.这就是很典型的面向过程的思维方式:怎么做,需要什

用new去调用一个函数

//当new去调用一个函数 : 这个时候函数中的this就是创建出来的对象,而且函数的的返回值直接就是this啦(隐式返回) //new后面调用的函数 : 叫做构造函数 function CreatePerson(name){ this.name = name; this.showName = function(){ alert( this.name ); }; } var p1 = new CreatePerson('小明'); //p1.showName(); var p2 = new Cr

java如果去请求一个网页的数据

我们可以通过在java程序中模拟浏览器一样,把数据抓下来,具体方法是在java程序中set header和cookie,下面是一个例子: public class NetConnection { public static final int MAX_HOTWORDS_FILE_SIZE = 256 * 1024; public static void main(String[] args) { send("http://tuan.aibang.com/shenzhen/new_2033549.

分享:怎么去测试一个 app 是否存在安全问题?

怎么去测试一个 app 是否存在安全问题,面对这类安全性测试,是app专项测试中必须要做的一环, 简单列举下目前常做的测试类别 1. 用户隐私 检查是否在本地保存用户密码,无论加密与否 检查敏感的隐私信息,如聊天记录.关系链.银行账号等是否进行加密 检查是否将系统文件.配置文件明文保存在外部设备上 部分需要存储到外部设备的信息,需要每次使用前都判断信息是否被篡改 2. 文件权限 检查App所在的目录,其权限必须为不允许其他组成员读写 3. 网络通讯 检查敏感信息在网络传输中是否做了加密处理,重要