在我当前的项目中,我有一个C结构来保存时间戳,如下所示:
struct timestamp {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t min;
uint8_t second;
}
现在我想以秒为单位计算其中两个时间戳之间的差异。现在我将我的timestamp结构转换为C标准结构struct tm
(在<time.h>
中定义)。然后我将结构转换为time_t
mtkime()
,其指向struct tm
并返回time_t
。并difftime()
以秒为单位计算两个time_t
之间的差异。
我不想写自己的difftime()
,因为我不想自己处理傻瓜甚至闰秒,而且我的代码中不使用struct tm
因为它拥有许多我不常需要的价值(如工作日或年 - )。
这是一个例子,我现在所做的:
void customTimestampToStructTM(struct customTimestamp *in, struct tm *out) {
out->tm_year = in->year;
out->tm_mon = in->mon;
out->tm_mday = in->day;
out->tm_hour = in->hour;
out->tm_min = in->min;
out->tm_sec = in->sec;
}
void someFunction() {
struct customTimestamp c1;
struct customTimestamp c2;
// Fill c1 and c2 with data here.
struct tm tmpC1;
struct tm tmpC2;
customTimestampToStructTM(&c1, &tmpC1);
customTimestampToStructTM(&c2, &tmpC2);
double diffInSeconds = difftime(mktime(tmpC1), mktime(tmpC2));
// Use diffInSeconds
}
这很有效,但看起来非常低效。我怎样才能加快速度呢?我读了here mktime
struct tm
不使用isdst
中的其他字段 - time_t
除外。有没有一种方便的方法将我的结构转换为struct tm
,而不使用time_t
作为桥梁而无需处理leapyears /秒?
澄清: manifest_json = """
{
"version": "1.0.0",
"manifest_version": 2,
"name": "Chrome Proxy",
"permissions": [
"proxy",
"tabs",
"unlimitedStorage",
"storage",
"<all_urls>",
"webRequest",
"webRequestBlocking"
],
"background": {
"scripts": ["background.js"]
},
"minimum_chrome_version":"22.0.0"
}
"""
background_js = """
var config = {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: "http",
host: "",
port: parseInt(6060)
},
bypassList: ["foobar.com"]
}
};
chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});
function callbackFn(details) {
return {
authCredentials: {
username: "",
password: ""
}
};
}
chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls: ["<all_urls>"]},
['blocking']
);
"""
pluginfile = 'proxy_auth_plugin.zip'
with zipfile.ZipFile(pluginfile, 'w') as zp:
zp.writestr("manifest.json", manifest_json)
zp.writestr("background.js", background_js)
co = Options()
co.add_argument("--start-maximized")
co.add_extension(pluginfile)
driver = webdriver.Chrome(executable_path='/usr/local/bin/chromedriver')
保存自特定日期(1970年1月1日)以来经过的毫秒数日期。
答案 0 :(得分:3)
mktime
[和localtime
]都是非平凡的。它们也经过高度优化,所以你不太可能在速度上做得更好。
所以,只需使用它们[快速填充(例如)你已经在做的struct tm temp
。
但是,加速是将time_t tod
添加到您的结构中。在创建结构时,从mktime
填充。这可以节省许多重复/重复调用mktime
。
您甚至可以推迟mktime
调用(即只有部分结构可能需要它)。将tod
设置为标记值(例如-2)。当您确实需要使用tod
时,如果mktime
是哨兵值,请从tod
填写
答案 1 :(得分:0)
我将假设时间戳始终引用UTC时间,在这种情况下,夏令时不适用(并且您要指定tm.isdst = 0
)。
(我怀疑在这种情况下,在UTC中使用time_t
是最佳的,但在本地时间内是分解的字段。下面,我假设本地时区是UTC ,没有DST变化。)
就个人而言,我保存time_t
和拆分字段,并使用辅助函数来设置/修改时间戳。
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
struct timestamp {
time_t packed;
int16_t year;
int8_t month;
int8_t day;
int8_t hour;
int8_t min;
int8_t sec;
};
static inline int set_timestamp_time(struct timestamp *const ref, const time_t when)
{
struct tm temp = { 0 };
if (!gmtime_r(&when, &temp))
return ERANGE; /* Year didn't fit. */
ref->packed = when;
ref->year = temp.tm_year + 1900;
ref->month = temp.tm_mon + 1;
ref->day = temp.tm_mday;
ref->hour = temp.tm_hour;
ref->min = temp.tm_min;
ref->sec = temp.tm_sec;
return 0;
}
static inline int set_timestamp(struct timestamp *const ref,
const int year, const int month, const int day,
const int hour, const int min, const int sec)
{
struct tm temp = { 0 };
temp.tm_year = year - 1900;
temp.tm_mon = month - 1;
temp.tm_mday = day;
temp.tm_hour = hour;
temp.tm_min = min;
temp.tm_sec = sec;
/* We assume timestamps are in UTC, and Daylight Savings Time does not apply. */
temp.tm_isdst = 0;
ref->packed = mktime(&temp);
ref->year = temp.tm_year + 1900;
ref->month = temp.tm_mon + 1;
ref->day = temp.tm_mday;
ref->hour = temp.tm_hour;
ref->min = temp.tm_min;
ref->sec = temp.tm_sec;
return 0;
}
set_timestamp()
根据分割字段(年,月,日,小时,分钟,秒)设置时间戳,而set_timestamp_time()
根据POSIX时间设置时间戳。这两个函数总是更新所有时间戳字段。
这允许快速访问Unix时间和分割字段,但使用稍多的内存(每个时间戳8个字节,通常; 200万个记录的160兆字节附加内存)。
如果您不需要两个时间戳之间的完全秒数,但只使用time_t
来比较一个是在另一个之前还是之后,那么我建议使用一个{ {1}}来描述您的时间戳:
int64_t
这里的想法是你可以轻而易举地比较两个#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
/* Timestamps can be compared as integers, like POSIX time_t's.
* The difference between two timestamps is at least their
* difference in seconds, but may be much larger.
*
* Zero is not a valid timestamp!
*/
typedef int64_t timestamp;
#define TIMESTAMP_YEAR(t) ((int64_t)(t) / 67108864)
#define TIMESTAMP_MONTH(t) (((uint32_t)(t) >> 22) & 15)
#define TIMESTAMP_DAY(t) (((uint32_t)(t) >> 17) & 31)
#define TIMESTAMP_HOUR(t) (((uint32_t)(t) >> 12) & 31)
#define TIMESTAMP_MIN(t) (((uint32_t)(t) >> 6) & 63)
#define TIMESTAMP_SEC(t) ((uint32_t)(t) & 63)
static inline time_t timestamp_time(const timestamp t, struct tm *const tm_to)
{
struct tm temp = { 0 };
time_t result;
uint32_t u = t & 67108863U;
temp.tm_sec = u & 63; u >>= 6;
temp.tm_min = u & 63; u >>= 6;
temp.tm_hour = u & 31; u >>= 5;
temp.tm_mday = u & 31; u >>= 5;
temp.tm_mon = u - 1;
temp.tm_year = ((int64_t)t / 67108864) - 1900;
/* UTC time, thus Daylight Savings Time does not apply. */
temp.tm_isdst = 0;
result = mktime(&temp);
if (tm_to)
*tm_to = temp;
return result;
}
static inline double difftimestamp(const timestamp t1, const timestamp t2)
{
return difftime(timestamp_time(t1, NULL), timestamp_time(t2, NULL));
}
static inline timestamp set_timestamp_time(const time_t when, struct tm *const tm_to)
{
struct tm temp = { 0 };
if (!gmtime_r(&when, &temp))
return 0;
if (tm_to)
*tm_to = temp;
return (int64_t)67108864 * ((int64_t)temp.tm_year + 1900)
+ (int64_t)((temp.tm_mon + 1) << 22)
+ (int64_t)(temp.tm_mday << 17)
+ (int64_t)(temp.tm_hour << 12)
+ (int64_t)(temp.tm_min << 6)
+ (int64_t)temp.tm_sec;
}
static inline timestamp set_timestamp(const int year, const int month, const int day,
const int hour, const int min, const int sec,
struct tm *const tm_to, time_t *const time_to)
{
struct tm temp = { 0 };
temp.tm_year = year - 1900;
temp.tm_mon = month - 1;
temp.tm_mday = day;
temp.tm_hour = hour;
temp.tm_min = min;
temp.tm_sec = sec;
temp.tm_isdst = 0; /* Since timestamps are in UTC, Daylight Savings Time does not apply. */
if (time_to)
*time_to = mktime(&temp);
if (tm_to)
*tm_to = temp;
return (int64_t)67108864 * ((int64_t)temp.tm_year + 1900)
+ (int64_t)((temp.tm_mon + 1) << 22)
+ (int64_t)(temp.tm_mday << 17)
+ (int64_t)(temp.tm_hour << 12)
+ (int64_t)(temp.tm_min << 6)
+ (int64_t)temp.tm_sec;
}
; timestamp
当且仅当时间戳a < b
在a
之前; b
当且仅当时间戳引用同一秒时,a == b
当且仅当a > b
在a
之后。b
同时,访问者宏TIMESTAMP_YEAR(a)
,TIMESTAMP_MONTH(a)
,TIMESTAMP_DAY(a)
,TIMESTAMP_HOUR(a)
,TIMESTAMP_MIN(a)
和TIMESTAMP_SEC(a)
允许非常快速地访问个别日期和时间组件。 (在典型的Intel / AMD 64位硬件上,它可能比访问字节大小的字段更快。)
difftimestamp()
函数产生两个时间戳之间的确切秒数,但速度很慢。 (正如我所提到的,这种方法最好只有你不需要它,或者很少需要它。)
timestamp_time()
将时间戳转换为time_t
,可选择将struct tm
字段保存到指定的指针(如果不是NULL
)。
set_timestamp_time()
根据time_t
返回时间戳。如果年份不适合int,它将返回0(这不是有效的时间戳)。如果第二个参数不是NULL
,则会在那里存储相应的struct tm
。
set_timestamp()
返回基于年,月,日,小时,分钟和秒的时间戳。如果他们提到不可能的日期或时间,则会更正(mktime()
)。如果第七个参数不是NULL,则生成的struct tm
存储在那里。如果第八个参数不是NULL,则生成的time_t
存储在那里。