在C++中如何创建日期对象?

huangapple go评论57阅读模式
英文:

How to create date object in C++?

问题

在C++中创建Date对象的正确方法是使用std::chrono::year_month_day结构,然后转换为std::chrono::system_clock::time_point。以下是类似于Python代码的C++示例:

#include <iostream>
#include <chrono>

int main() {
    std::chrono::year_month_day ymd{std::chrono::year{2020}, std::chrono::month{5}, std::chrono::day{17}};
    std::chrono::system_clock::time_point tp = std::chrono::sys_days(ymd);
    
    std::chrono::days delta(1);
    tp += delta;
    
    // 输出日期
    std::time_t tt = std::chrono::system_clock::to_time_t(tp);
    std::tm tm = *std::localtime(&tt);
    
    std::cout << "Year: " << tm.tm_year + 1900 << ", Month: " << tm.tm_mon + 1 << ", Day: " << tm.tm_mday << std::endl;
    
    return 0;
}

这段代码演示了如何在C++中创建日期对象,并进行日期运算,类似于Python中的示例。

英文:

What is the proper way to create Date object in C++?
I want C++ analogy of this python code:

import datetime

x = datetime.date(2020, 5, 17)
delta = datetime.timedelta(days=1)
x = x + delta

I was reading about chrono and found only time_point https://en.cppreference.com/w/cpp/chrono/time_point

but I don't see constructor like this date(year=2020, month=1, day=2)

答案1

得分: 10

chrono直到C++20才添加了日历支持,各种实现仍在努力改进。Microsoft VC++目前已经实现并发布了完整的规范。否则,你可以使用我的免费、开源库,支持C++11/14/17,它实现了新的chrono日历支持,但位于date命名空间。我会介绍C++20,只要知道如果不可用,有一种解决方法。

C++20有两种(或更多)日期类型,主要是以下两种:

  • sys_days
  • year_month_day

sys_days是基于system_clockchrono::time_point,但精度为days。实际上,它是以下类型的类型别名:

time_point<system_clock, days>

这个类型只是保存自1970-01-01以来的天数的整数计数(对于负值来说是之前的天数)。这使得它非常高效地进行面向天的算术运算。它还很擅长转换为日期时间类型,即具有比days更精确的精度的任何system_clock基础的time_point,比如system_clock::time_point(通常是微秒到纳秒精度)。

year_month_day是一个{year, month, day}数据结构。它非常适合进行年份和月份的算术运算,并且可以非常高效地访问年份、月份和日期字段。

可以在sys_daysyear_month_day之间进行隐式转换,无论是在哪个方向都不会丢失信息。

year_month_day ymd = ...;  // 一些日期
sys_days       sd = ymd;   // 不同数据结构中的相同日期
ymd = sd;                  // 往返转换 - 值不变

可以使用“传统语法”轻松创建year_month_day,例如:

auto ymd = 2020y/5/17;

ymd的类型是year_month_day,年份为2020,月份为5(或者是五月),日期为17。2020后面的y后缀表示year的值,'/'运算符假定接下来的两个整数分别表示月份和日期。

还有两种可行的顺序:month/day/yearday/month/year。只要第一个字段是强类型的,后面两个字段可以是强类型的,也可以只是int。

auto ymd2 = May/17/2020;  // ymd2 == ymd
auto ymd3 = 17d/5/2020;   // ymd3 == ymd

你的示例代码可以写成:

sys_days x = 2020y/5/17;
x += days{1};
  • 传统语法创建了一个year_month_day,它隐式转换为sys_days
  • 将一天添加到值,创建了一个等于2020y/5/18的sys_days

C++20中的其他日期类型包括:

  • local_days:适用于保留时区本地日期与UTC日期之间的差异。
  • year_month_weekday:适用于指定日期,例如2020年5月的第三个星期日(Sunday[3]/May/2020)。

可以在各种日期类型之间进行互相转换,例如:

year_month_day ymd4{Sunday[3]/May/2020};  // ymd4 == ymd
英文:

chrono doesn't add calendrical support until C++20, and the various implementations are still working on that. Microsoft VC++ is solidly out front and currently shipping the full spec. Otherwise you can use my free, open source library with C++11/14/17 which implements the new chrono calendrical support, except it is in namespace date. I'll describe C++20, just know that if that isn't available to you, there's a workaround for that.

C++20 has two (or more) date types. These are the main two:

  • sys_days
  • year_month_day

sys_days is a chrono::time_point based on system_clock, but with a precision of days. It is actually a type alias for:

time_point&lt;system_clock, days&gt;

All this type does is hold an integral count of days after 1970-01-01 (or before for negative values). This makes it very efficient at day-oriented arithmetic. It is also good at converting to a date-time type, which is just any system_clock-based-time_point with a precision finer than days, such as system_clock::time_point (typically microseconds to nanoseconds precision).

year_month_day is a {year, month, day} data structure. It is very good at year and month arithmetic. And it has very efficient access to the year, month and day fields.

One can implicitly convert between sys_days and year_month_day, in either direction, with no information loss.

year_month_day ymd = ...;  // some date
sys_days       sd = ymd;   // the same date in a different data structure
ymd = sd;                  // round trip - no change in value

One can easily create a year_month_day with "conventional syntax", for example:

auto ymd = 2020y/5/17;

ymd has type year_month_day, with the year 2020, the month 5 (or May), and the day 17. The y suffix on 2020 denotes a value of year, and the '/' operators assume the next two integers represent month and day in that order.

Two other orders are permissible: month/day/year and day/month/year. As long as the first field is strongly typed, the following two fields can be either strongly typed, or just int.

auto ymd2 = May/17/2020;  // ymd2 == ymd
auto ymd3 = 17d/5/2020;   // ymd3 == ymd

Your example code can be written:

sys_days x = 2020y/5/17;
x += days{1};
  • The conventional syntax creates a year_month_day which implicitly converts to sys_days.
  • One day is added to the value creating a sys_days equal to 2020y/5/18.

Other date types in C++20 include:

  • local_days : good for keeping the difference between the date local to a time zone, as opposed to UTC.
  • year_month_weekday : good for specifying dates such as the third Sunday of May 2020 (Sunday[3]/May/2020).

One can inter-convert among the various date types, for example:

year_month_day ymd4{Sunday[3]/May/2020};  // ymd4 == ymd

答案2

得分: 4

A date object is available in the standard library since c++20.

#include &lt;chrono&gt;
#include &lt;iostream&gt;

int main ()
{
    std::chrono::year_month_day date(
        std::chrono::year(2023), 
        std::chrono::month(5), 
        std::chrono::day(7));

    std::cout &lt;&lt; &quot;Year: &quot; &lt;&lt; static_cast&lt;int&gt;(date.year())
              &lt;&lt; &quot;, Month: &quot; &lt;&lt; static_cast&lt;unsigned&gt;(date.month())
              &lt;&lt; &quot;, Day: &quot; &lt;&lt; static_cast&lt;unsigned&gt;(date.day()) &lt;&lt; &#39;\n&#39;;
}

Demo

Even though stream output should exist it is not available in the demo environment above, hence the manual cast of each value prior to output.

Arithmetic operations like the one you mention are provided either as:

Note that the year(), month(), day() methods return objects that are not the same as the corresponding specializations for duration (std::chrono::years, std::chrono::months, std::chrono::days) but merely integral representations of the count of such quantities (hence the static cast to int is ok). That said, you can perform arithmetic operations with the corresponding durations.

英文:

A date object is available in the standard library since c++20.

#include &lt;chrono&gt;
#include &lt;iostream&gt;


int main ()
{
    std::chrono::year_month_day date(
        std::chrono::year(2023), 
        std::chrono::month(5), 
        std::chrono::day(7));

    std::cout &lt;&lt; &quot;Year: &quot; &lt;&lt; static_cast&lt;int&gt;(date.year())
              &lt;&lt; &quot;, Month: &quot; &lt;&lt; static_cast&lt;unsigned&gt;(date.month())
              &lt;&lt; &quot;, Day: &quot; &lt;&lt; static_cast&lt;unsigned&gt;(date.day()) &lt;&lt; &#39;\n&#39;;
}

Demo

Even though stream output should exist it is not available in the demo environment above, hence the manual cast of each value prior to output.

Arithmetic operations like the one you mention are provided either as:

Note that the year(), month(), day() methods return object that are not the same as the corresponding specializations for duration (std::chrono::years, std::chrono::months, std::chrono::days) but merely integral representation of the count of such quantities (hence the static cast to int is ok). That said, you can perform arithmetic operations with the corresponding durations.

huangapple
  • 本文由 发表于 2023年5月8日 01:52:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76195444.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定