Eis*_*eim 1 c++ linux timestamp utc localtime
我正在开发一个客户端-服务器自定义应用程序(将在 linux 上运行),我发送的其中一个帧包含时间戳(即发送帧的时间)。
为了使我的应用程序可靠,我曾经gmtime在客户端上生成时间。我在比利时,所以现在客户端 VM 的时间比 UTC 时间晚 2 小时(因为夏季时间)。
在服务器端,我首先将接收到的字符串转换为time_t类型。我这样做是为了使用该difftime函数来查看时间戳是否太旧。然后,我再次使用 生成时间戳(UTC 时间)gmtime,并将其转换为time_t.
然后我比较两者time_t以查看时差。
我在服务器端转换时间时遇到问题。我使用与客户端相同的代码,但输出gmtime不同...
客户端:生成时间戳的函数,并将其导出为字符串 ( time_str):
std::string getTime()
{
time_t rawtime;
struct tm * timeinfo;
char buffer[80];
time (&rawtime); // Get time of the system
timeinfo = gmtime(&rawtime); // Convert it to UTC time
strftime(buffer,80,"%d-%m-%Y %H:%M:%S",timeinfo);
std::string time_str(buffer); // Cast it into a string
cout<<"Time Stamp now (client) : "<<time_str<<endl;
return time_str;
}
Run Code Online (Sandbox Code Playgroud)
它产生了这个(在当地时间 9 点 33 分):
现在时间戳:06-04-2016 07:33:30
服务器端:检索时间戳,生成newx时间戳,并比较它们的功能:
bool checkTimeStamp(std::string TimsStamp_str, double delay)
{
cout<<"TimeStamp recieved: "<<TimsStamp_str<<endl;
/* Construct tm from string */
struct tm TimeStampRecu;
strptime(TimsStamp_str.c_str(), "%d-%m-%Y %I:%M:%S", &TimeStampRecu);
time_t t_old = mktime(&TimeStampRecu);
/* Generate New TimeStamp */
time_t rawtime;
struct tm * timeinfo;
time (&rawtime); // Get time of the system
timeinfo = gmtime(&rawtime); // convert it to UTC time_t
time_t t2 = mktime(timeinfo); // Re-Cast it to timt_t struct
/* Convert it into string (for output) */
char buffer[80];
strftime(buffer,80,"%d-%m-%Y %H:%M:%S",timeinfo);
std::string time_str(buffer); // Cast it into a string
cout<<"Time Stamp now (server) : "<<time_str<<endl;
/* Comparison */
double diffSecs = difftime(t2, t_old);
cout<<diffSecs<<endl;
bool isTimeStampOK;
if (diffSecs < delay)
isTimeStampOK = true;
else
isTimeStampOK = false;
return isTimeStampOK;
}
Run Code Online (Sandbox Code Playgroud)
它产生了这个(在比利时 9h33):
收到时间戳:06-04-2016 07:33:30
现在时间戳(服务器):06-04-2016 08:33:31
为什么服务器时间 (8h33) 既不是本地时间 (9h33),也不是 UTC 时间 (7h33)?
我在它的世代中犯了错误吗?我不明白在哪里,因为这些代码与客户端完全相同......
你的代码中有几个错误,有些是你的错,有些不是。这里最大的问题是 C <time.h>API 非常糟糕、混乱、不完整和容易出错,以至于像这样的错误几乎是强制性的。稍后再谈。
第一个问题是这一行:
struct tm TimeStampRecu;
Run Code Online (Sandbox Code Playgroud)
它创建一个未初始化的对象tm,然后将其传递给strptime. strptime可能不会填写 的所有字段TimeStampRecu。您应该TimeStampRecu像这样进行零初始化:
struct tm TimeStampRecu{};
Run Code Online (Sandbox Code Playgroud)
下一个问题:
strptime(TimsStamp_str.c_str(), "%d-%m-%Y %I:%M:%S", &TimeStampRecu);
Run Code Online (Sandbox Code Playgroud)
由 表示的 12 小时时间在%I没有 AM/PM 说明符的情况下是不明确的。我怀疑这只是一个类型,因为它是你唯一使用它的地方。
下一个问题:
gmtime time_t -> tm UTC to UTC
mktime tm -> time_t local to UTC
Run Code Online (Sandbox Code Playgroud)
也就是说,根据运行它的计算机的本地时间来mtkime解释输入tm。你需要的是:
timegm tm -> time_t UTC to UTC
Run Code Online (Sandbox Code Playgroud)
不幸的timegm是,这不是标准的 C(或 C++)。幸运的是,它可能无论如何都存在于您的系统中。
通过这些更改,我认为您的代码将按预期运行。
如果您使用的是 C++11,这里有一个更安全的日期/时间库(免费/开源):
https://github.com/HowardHinnant/date
这是您的代码转换为使用此更高级别的库:
std::string getTime()
{
using namespace std::chrono;
auto rawtime = time_point_cast<seconds>(system_clock::now());
auto time_str = date::format("%d-%m-%Y %H:%M:%S", rawTime);
std::cout<<"Time Stamp now (client) : "<<time_str<< '\n';
return time_str;
}
bool checkTimeStamp(std::string TimsStamp_str, std::chrono::seconds delay)
{
using namespace std::chrono;
std::cout<<"TimeStamp recieved: "<<TimsStamp_str<< '\n';
/* Construct tm from string */
std::istringstream in{TimsStamp_str};
time_point<system_clock, seconds> t_old;
date::parse(in, "%d-%m-%Y %H:%M:%S", t_old);
/* Generate New TimeStamp */
auto rawtime = time_point_cast<seconds>(system_clock::now());
auto time_str = date::format("%d-%m-%Y %H:%M:%S", rawTime);
in.str(time_str);
time_point<system_clock, seconds> t2;
date::parse(in, "%d-%m-%Y %H:%M:%S", t2);
cout<<"Time Stamp now (server) : "<<time_str<<endl;
/* Comparison */
auto diffSecs = t2 - t_old;
cout<<diffSecs.count()<<endl;
bool isTimeStampOK;
if (diffSecs < delay)
isTimeStampOK = true;
else
isTimeStampOK = false;
return isTimeStampOK;
}
Run Code Online (Sandbox Code Playgroud)