以更优雅的方式获得C++的当年

More elegant way to get the current year in C++

本文关键字:C++ 方式获      更新时间:2023-10-16

我对C++很陌生。我需要获取当前年份并将其存储在 int 中。

我得出了这个解决方案:

std::time_t result = std::time(nullptr);
std::istringstream iss(ctime(&result));
iss.ignore(20);
int year;
iss >> year;

我发现这个解决方案有点丑陋,即使它有效,因为它看起来不是很强大,而且需要很多步骤才能做很多事情。

有没有更好的方法

C++20,您可以使用std::chrono来实现此目的。

P0355R7扩展到日历和时区

#include <iostream>
#include <format>
#include <chrono>
int main()
{
const auto now = std::chrono::system_clock::now();
std::cout << std::format("{:%Y}", now); // => 2021
}

在我看来,通过字符串解析将time_t转换为字符串似乎不必要的复杂且容易出错。正如@Ted的评论中所抱怨的那样,这可能会引入文本输出的本地化,这可能会使解析不可靠。

连同std::time(),有可用的

  • std::localtime()

    将自纪元以来的给定时间(作为 std::time_t 值(转换为以本地时间表示的日历时间。

  • std::gmtime()

    自纪元以来的给定时间作为 std::time_t 值转换为日历时间,以协调世界时 (UTC( 表示。

两者都返回指向包含公共成员的struct tm的指针

自1900年以来的int tm_year

一个小样本:

#include <ctime>
#include <iostream>
int main()
{
std::time_t t = std::time(nullptr);
std::tm *const pTInfo = std::localtime(&t);
std::cout << "Current year: " << 1900 + pTInfo->tm_year << 'n';
}

输出:

Current year: 2019

科里鲁的现场演示

#include <ctime>
#include <iostream>
using namespace std;
int main()
{
time_t current_time;
current_time = time(NULL);
int a;
a = 1970 + current_time / 31537970; 
cout << a << " is the current year.";
return 0;
}

简而言之,以下get_this_year()函数应该以 C++20 的方式为您工作。

它将返回当年的int

// year.cpp
#include <chrono>
#include <iostream>
int get_current_year() {
using namespace std::chrono;
return static_cast<int>(
year_month_day{time_point_cast<days>(system_clock::now())}.year());
}
int main() {
int year = get_current_year();
std::cout << year << std::endl; // 2022
}

这应该编译为例如g++ -std=c++20 year.cpp.


但我也想以冗长的方式扩展它,解释每一步发生了什么。

// year.cpp
#include <chrono>
#include <iostream>
int get_current_year() {
using namespace std::chrono;
auto now = system_clock::now();           // 1. get time_point for now
auto today = time_point_cast<days>(now);  // 2. cast to time_point for today
auto ymd = year_month_day(today);         // 3. convert to year_month_day 
auto year = ymd.year();                   // 4. get year from year_month_day
return static_cast<int>(year);            // 5. an explicit cast is required 
}
int main() {
int year = get_current_year();
std::cout << year << std::endl; // 2022
}

现在,更详细地,明确拼写出所有类型 -

// year.cpp
#include <chrono>
#include <iostream>
int get_current_year() {
std::chrono::time_point<std::chrono::system_clock,
std::chrono::system_clock::duration>
now = std::chrono::system_clock::now();
std::chrono::time_point<std::chrono::system_clock, std::chrono::days> today =
std::chrono::time_point_cast<std::chrono::days>(now);
std::chrono::year_month_day ymd = std::chrono::year_month_day(today);
std::chrono::year year = ymd.year();
return static_cast<int>(year);
}
int main() {
int year = get_current_year();
std::cout << year << std::endl; // 2022
}

基本上有两种类型的格式来表示时间点:

  1. 基于序列 - 例如,此时间点是自纪元以来的x秒(例如 1970 年 1 月 1 日(
  2. 基于字段 - 例如,此时间点是year/month/day

从系统时钟中,我们得到一个基于串行的时间点。我们需要将其转换为基于字段的时间点。然后从这个基于字段的时间点中提取年份。

这里有一个简单的方法:

string timestamp_str = __TIMESTAMP__;
auto timestamp_tokens = split(timestamp_str, ' ');
std::cout << timestamp_tokens[timestamp_tokens.size() - 1] << std::endl;

split((函数通过分隔符"空格"拆分字符串。您可以编写一个自定义方法来获取最后一个令牌(最后一个令牌是年份(。你可以从这个链接获取split((的实现。下面是一个示例实现:

vector<string> split(string string_with_delim, char delim)
{
auto i = 0;
vector<string> result;
auto pos = string_with_delim.find(delim);
while(pos != string::npos)
{
string res = string_with_delim.substr(i, pos-i);
result.push_back(res);
i = ++pos;
pos = string_with_delim.find(delim, pos);
}
result.push_back(string_with_delim.substr(i, string_with_delim.size()));
return result;
}