首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在自定义Epoc之后的给定天数内计算日期

在自定义Epoc之后的给定天数内计算日期
EN

Stack Overflow用户
提问于 2015-11-12 22:09:28
回答 1查看 194关注 0票数 3

我有一个自定义的Epoc日期,它不同于STL中的硬编码Epoc。我想找出具体天数后的新日期。

代码语言:javascript
复制
std::string ReturnDateTimeAsString(long double NumberOfDaysSinceEpoc)
{
    std::istringstream iss("1200-01-01.00:00:00");  // My custom Epoc
    std::tm Time;
    iss >> std::get_time(&Time, "%Y-%m-%d.%H:%M:%S");
    std::chrono::system_clock::time_point MyEpoc = std::chrono::system_clock::from_time_t(std::mktime(&Time));
    std::chrono::duration<long double, std::ratio<86400, 1>> Days(NumberOfDaysSinceEpoc);   // 86400: Seconds in a day
    std::chrono::system_clock::time_point DateTime = MyEpoc + Days; // I get the error here!
    std::time_t TimeType = std::chrono::system_clock::to_time_t(DateTime);
    return std::string(std::ctime(&TimeType));
}

函数参数可以是十进制的。例如,如果我将4.25传递给此函数,我希望从中获得字符串"1200-01-05.06:00:00" (Epoc后4天零6小时)。

我在尝试添加Epoc和Days变量的那一行中得到了下面的错误消息。

代码语言:javascript
复制
Cannot convert from 'std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<long double,std::ratio<0x01,0x0989680>>>'
to
'std::chrono::time_point<std::chrono::system_clock,std::chrono::system_clock::duration>'

No suitable user-defined conversion from
"std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<long double, std::ratio<1i64, 10000000i64>>>"
to
"std::chrono::system_clock::time_point"

我如何修复这段代码?

EN

回答 1

Stack Overflow用户

发布于 2015-11-13 00:11:16

忽略命名空间,MyEpoc的类型为system_clock::time_pointDays的类型为duration<long double, ratio<86400>>。这两种类型的总和将具有类型:

代码语言:javascript
复制
time_point<system_clock, duration<long double, system_clock::period>>

您正在尝试将该类型分配给:

代码语言:javascript
复制
system_clock::time_point

这与以下内容相同:

代码语言:javascript
复制
time_point<system_clock, system_clock::duration>

system_clock::duration被指定为某种有符号整数类型(通常为long long)。因此,整个问题在于试图将long double-based time_point转换为基于整数的time_point。这可以使用time_point_cast来完成

代码语言:javascript
复制
std::chrono::system_clock::time_point DateTime = 
  std::chrono::time_point_cast<std::chrono::system_clock::duration>(MyEpoc + Days);

这是否使您的函数正确则是另一回事。但这会使类型系统正常工作。

使用这个date library,我可以很容易地看到,至少在我的系统上,你的纪元并不是你想要的:

代码语言:javascript
复制
#include "date.h"

std::string
ReturnDateTimeAsString(long double NumberOfDaysSinceEpoc)
{
    using namespace std;
    using namespace std::chrono;

    istringstream iss("1200-01-01.00:00:00");  // My custom Epoc
    tm Time;
    iss >> get_time(&Time, "%Y-%m-%d.%H:%M:%S");
    system_clock::time_point MyEpoc = system_clock::from_time_t(mktime(&Time));
    {
        using namespace date;
        std::cout << MyEpoc << '\n';
    }
    duration<long double, ratio<86400, 1>> Days(NumberOfDaysSinceEpoc);   // 86400: Seconds in a day
    system_clock::time_point DateTime = time_point_cast<system_clock::duration>(MyEpoc + Days); // I get the error here!
    time_t TimeType = system_clock::to_time_t(DateTime);
    return string(ctime(&TimeType));
}

这是纪元的输出:

代码语言:javascript
复制
1969-12-31 23:59:59.000000

mtkime,至少在我的系统上,可能在1200-01-01之前是无效的。

事实证明,在我的系统上,这个操作受到numeric_limits<int32_t>::min()秒(-2'147'483'648s)的限制。sys_days{1970_y/1/1} - 2'147'483'648s是1901-12-13 20:45:52。尝试将纪元设置得更早,我的系统(OS )就会崩溃。

使用这个date library,我简化了你的函数,并且它正在正确地测试,假设你想要你的纪元在协调时区(如果不是,很容易改变它):

代码语言:javascript
复制
#include "date.h"

using days_ld = std::chrono::duration<long double, std::ratio<86400>>;

std::string
ReturnDateTimeAsString(days_ld Days)
{
    using namespace std;
    using namespace std::chrono;
    using namespace date;

    constexpr auto MyEpoc = sys_days{1200_y/1/1};
    auto DateTime = round<seconds>(MyEpoc + Days);
    ostringstream out;
    out << DateTime;
    return out.str();
}

int
main()
{
    std::cout << ReturnDateTimeAsString(days_ld{4.25}) << '\n';
}

这将输出以下内容:

代码语言:javascript
复制
1200-01-05 06:00:00

我随意将您的long double输入四舍五入为最近的seconds。如果你更喜欢更好的东西,比如milliseconds,这是一个简单的改变:

代码语言:javascript
复制
    auto DateTime = round<milliseconds>(MyEpoc + Days);

它将输出更改为:

代码语言:javascript
复制
1200-01-05 06:00:00.000

或者:

代码语言:javascript
复制
auto DateTime = round<minutes>(MyEpoc + Days);

它将输出更改为:

代码语言:javascript
复制
1200-01-05 06:00

通过将函数的参数更改为所需的持续时间类型(days_ld),您的函数现在使用起来更安全,也更灵活。例如,您的客户端现在还可以输入std::chrono::hours

代码语言:javascript
复制
    using namespace std::chrono_literals;
    std::cout << ReturnDateTimeAsString(102h) << '\n';

并得到相同的输出。

如果您喜欢输出字符串的其他格式,这也是非常简单的。有关更多详细信息,请访问以下链接:

http://howardhinnant.github.io/date/date.html

https://github.com/HowardHinnant/date/wiki

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33673386

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档