1

我从我的 C++ 应用程序中的数据库中获取时间戳作为 AnsiString。它看起来像这样“2017-09-12 09:35:10”。

现在我想将它解析回 Unix 时间戳。

AnsiString myDate = Query->Fields->FieldByName("MyDates")->AsString;
TDateTime = StrToDateTime(myDate);

在我的具体情况下,我得到以下日期:2017-08-10 08:43:35

但我得到的 Unixtimestamp 是:42957.363599537

这是01-01-1970 12:55:57计算回可读格式。

我在这里错过了什么?!...

4

3 回答 3

0

C++Builder 6 and later have a DateTimeToUnix() function in the DateUtils unit:

#include <SysUtils.hpp>
#include <DateUtils.hpp>

AnsiString myDateStr = Query->Fields->FieldByName("MyDates")->AsString;
TDateTime myDate = StrToDateTime(myDateStr);
__int64 myTimestamp = DateTimeToUnix(myDate);

If you are using C++Builder 5 or earlier, you can implement your own DateTimeToUnix() function like this:

#include <SysUtils.hpp>

// Days between TDateTime basis (12/31/1899) and Unix time_t basis (1/1/1970)
const __int64 UnixDateDelta = 25569;

__int64 DateTimeToMilliseconds(const TDateTime &ADateTime)
{
    TTimeStamp LTimeStamp = DateTimeToTimeStamp(ADateTime);
    return (__int64(LTimeStamp.Date) * MSecsPerDay) + LTimeStamp.Time;
}

__int64 DateTimeToUnix(const TDateTime &AValue)
{
    __int64 Result = abs(DateTimeToMilliseconds(UnixDateDelta) - DateTimeToMilliseconds(AValue)) / MSecsPerSec;
    if (AValue < UnixDateDelta)
        Result = -Result;
    return Result;
}

Also note that the version of StrToDateTime() you are using is subject to the user's current locale settings for date/time. Since you are dealing with a very specific date/time format, I suggest you parse it manually and not rely on any particular locale, eg:

#include <SysUtils.hpp>
#include <stdio.h>

AnsiString myDateStr = Query->Fields->FieldByName("MyDates")->AsString;

Word wYear, wMonth, wDay, wHour, wMin, wSec;
sscanf(myDateStr.c_str(), "%hu-%hu-%hu %hu:%hu:%hu", &wYear, &wMonth, &wDay, &wHour, &wMin, &wSec);

TDateTime myDate = EncodeDate(wYear, wMonth, wDay) + EncodeTime(wHour, wMin, wSec, 0);
__int64 myTimestamp = DateTimeToUnix(myDate);

If you are using C++Builder 2006 or later, you can use the overloaded version of StrToDateTime() that accepts a TFormatSettings struct as input:

#include <SysUtils.hpp>
#include <DateUtils.hpp>

String myDateStr = Query->Fields->FieldByName("MyDates")->AsString;

TFormatSettings myFmt = TFormatSettings::Create();
myFmt.ShortDateFormat = _D("yyyy-mm-dd hh:nn:ss");
myFmt.DateSeparator = _D('-');
myFmt.TimeSeparator = _D(':');

TDateTime myDate = StrToDateTime(myDateStr, myFmt);
__int64 myTimestamp = DateTimeToUnix(myDate);
于 2017-09-12T21:33:39.697 回答
0

你得到的不是Unix 时间戳,而是TDateTime. 以下来自 Builder 的文档:

TDateTime 值的组成部分是自 1899 年 12 月 30 日以来经过的天数。TDateTime 值的小数部分是一天中的时间。

在其他情况下,Unix TimeStump 是从 01.01.1970 开始的秒数

于 2017-09-12T09:54:51.567 回答
0

您可以尝试Howard Hinnant 的免费、开源、仅标头、日期/时间库,它扩展了 C++11<chrono>标头以处理日历计算。

#include "date.h"
#include <iostream>
#include <sstream>

int
main()
{
    std::istringstream in{"2017-08-10 08:43:35"};
    date::sys_seconds Unixtimestamp;
    in >> date::parse("%F %T", Unixtimestamp);
    std::cout << Unixtimestamp.time_since_epoch().count() << '\n';
    std::cout << date::format("%F %T\n", Unixtimestamp);
}

输出:

1502354615
2017-08-10 08:43:35
于 2017-09-12T12:13:13.193 回答