- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我想打印或提取年/月/日值。
由于2038年的问题,我不想使用time_t
,但是我在网上找到的所有示例都使用它来将time_point
转换为tm
.
有没有简单的方法将time_point转换为tm(最好是不带boost)?
libc 中的 timesub 之类的实现将是我最后的手段: http://www.opensource.apple.com/source/Libc/Libc-262/stdtime/localtime.c
编辑:阅读建议的链接并进行更多研究后,我得出以下结论。
值得注意的是,Boost.Date_Time 可以是一个只有头文件的库。资源: http://www.boost.org/doc/libs/1_53_0/more/getting_started/unix-variants.html#header-only-libraries
最佳答案
用更好的算法更新答案,链接到算法的详细描述,并完全转换为 std::tm
.
I would like to print or extract year/month/day values. Is there a simple way to convert from time_point to tm (preferably without boost)?
首先要注意的是 std::chrono::time_point
不仅在 duration
上被模板化,而且在时钟上。时钟意味着一个时代。而且不同的时钟可以有不同的历元。
例如,在我的系统上,std::chrono::high_resolution_clock
和 std::chrono::steady_clock
有一个时代:每当计算机启动时。如果您不知道计算机何时启动,则无法转换 time_point
到任何日历系统。
话虽如此,您可能只是在谈论std::chrono::system_clock::time_point
, 如 time_point
, 只有这个 time_point
, 需要与公历(公历)具有确定性关系。
事实证明,std::chrono::system_clock
的每个实现我知道正在使用 unix time .这有一个忽略闰秒的 1970 年新年纪元。
标准不保证这一点。但是,如果您想使用以下公式,您可以利用这一事实:
首先,警告,我使用的是最新的 C++1y 草案,其中包括了新的 constexpr
工具。如果您需要退后一些 constexpr
编译器的属性,就这样做吧。
鉴于上述链接中的算法,您可以转换 std::chrono::time_point<std::chrono::system_clock, Duration>
到 std::tm
, 不使用 time_t
具有以下功能:
template <class Duration>
std::tm
make_utc_tm(std::chrono::time_point<std::chrono::system_clock, Duration> tp)
{
using namespace std;
using namespace std::chrono;
typedef duration<int, ratio_multiply<hours::period, ratio<24>>> days;
// t is time duration since 1970-01-01
Duration t = tp.time_since_epoch();
// d is days since 1970-01-01
days d = round_down<days>(t);
// t is now time duration since midnight of day d
t -= d;
// break d down into year/month/day
int year;
unsigned month;
unsigned day;
std::tie(year, month, day) = civil_from_days(d.count());
// start filling in the tm with calendar info
std::tm tm = {0};
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_wday = weekday_from_days(d.count());
tm.tm_yday = d.count() - days_from_civil(year, 1, 1);
// Fill in the time
tm.tm_hour = duration_cast<hours>(t).count();
t -= hours(tm.tm_hour);
tm.tm_min = duration_cast<minutes>(t).count();
t -= minutes(tm.tm_min);
tm.tm_sec = duration_cast<seconds>(t).count();
return tm;
}
还要注意 std::chrono::system_clock::time_point
在所有现有实现上是 UTC(忽略闰秒)时区的持续时间。如果要转换 time_point
使用另一个时区,您需要将时区的持续时间偏移添加/减去 std::chrono::system_clock::time_point
在将其转换为 days
的精度之前.如果您还想考虑闰秒,则在截断前调整适当的秒数到 days
使用 this table ,以及 unix 时间与 UTC现在对齐的知识。
这个函数可以通过以下方式验证:
#include <iostream>
#include <iomanip>
void
print_tm(const std::tm& tm)
{
using namespace std;
cout << tm.tm_year+1900;
char fill = cout.fill();
cout << setfill('0');
cout << '-' << setw(2) << tm.tm_mon+1;
cout << '-' << setw(2) << tm.tm_mday;
cout << ' ';
switch (tm.tm_wday)
{
case 0:
cout << "Sun";
break;
case 1:
cout << "Mon";
break;
case 2:
cout << "Tue";
break;
case 3:
cout << "Wed";
break;
case 4:
cout << "Thu";
break;
case 5:
cout << "Fri";
break;
case 6:
cout << "Sat";
break;
}
cout << ' ';
cout << ' ' << setw(2) << tm.tm_hour;
cout << ':' << setw(2) << tm.tm_min;
cout << ':' << setw(2) << tm.tm_sec << " UTC.";
cout << setfill(fill);
cout << " This is " << tm.tm_yday << " days since Jan 1\n";
}
int
main()
{
print_tm(make_utc_tm(std::chrono::system_clock::now()));
}
对我来说目前打印出来的是:
2013-09-15 Sun 18:16:50 UTC. This is 257 days since Jan 1
万一chrono-Compatible Low-Level Date Algorithms离线或移动,这里是 make_utc_tm
中使用的算法.在上面的链接中有对这些算法的深入解释。它们经过充分测试,并且具有非常大的有效性范围。
// Returns number of days since civil 1970-01-01. Negative values indicate
// days prior to 1970-01-01.
// Preconditions: y-m-d represents a date in the civil (Gregorian) calendar
// m is in [1, 12]
// d is in [1, last_day_of_month(y, m)]
// y is "approximately" in
// [numeric_limits<Int>::min()/366, numeric_limits<Int>::max()/366]
// Exact range of validity is:
// [civil_from_days(numeric_limits<Int>::min()),
// civil_from_days(numeric_limits<Int>::max()-719468)]
template <class Int>
constexpr
Int
days_from_civil(Int y, unsigned m, unsigned d) noexcept
{
static_assert(std::numeric_limits<unsigned>::digits >= 18,
"This algorithm has not been ported to a 16 bit unsigned integer");
static_assert(std::numeric_limits<Int>::digits >= 20,
"This algorithm has not been ported to a 16 bit signed integer");
y -= m <= 2;
const Int era = (y >= 0 ? y : y-399) / 400;
const unsigned yoe = static_cast<unsigned>(y - era * 400); // [0, 399]
const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1; // [0, 365]
const unsigned doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096]
return era * 146097 + static_cast<Int>(doe) - 719468;
}
// Returns year/month/day triple in civil calendar
// Preconditions: z is number of days since 1970-01-01 and is in the range:
// [numeric_limits<Int>::min(), numeric_limits<Int>::max()-719468].
template <class Int>
constexpr
std::tuple<Int, unsigned, unsigned>
civil_from_days(Int z) noexcept
{
static_assert(std::numeric_limits<unsigned>::digits >= 18,
"This algorithm has not been ported to a 16 bit unsigned integer");
static_assert(std::numeric_limits<Int>::digits >= 20,
"This algorithm has not been ported to a 16 bit signed integer");
z += 719468;
const Int era = (z >= 0 ? z : z - 146096) / 146097;
const unsigned doe = static_cast<unsigned>(z - era * 146097); // [0, 146096]
const unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399]
const Int y = static_cast<Int>(yoe) + era * 400;
const unsigned doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365]
const unsigned mp = (5*doy + 2)/153; // [0, 11]
const unsigned d = doy - (153*mp+2)/5 + 1; // [1, 31]
const unsigned m = mp + (mp < 10 ? 3 : -9); // [1, 12]
return std::tuple<Int, unsigned, unsigned>(y + (m <= 2), m, d);
}
template <class Int>
constexpr
unsigned
weekday_from_days(Int z) noexcept
{
return static_cast<unsigned>(z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6);
}
template <class To, class Rep, class Period>
To
round_down(const std::chrono::duration<Rep, Period>& d)
{
To t = std::chrono::duration_cast<To>(d);
if (t > d)
--t;
return t;
}
更新
最近,我将上述算法打包到免费提供的日期/时间库中 documented and available here .这个库可以很容易地从 std::system_clock::time_point
中提取年/月/日。 ,甚至小时:分钟:秒:小数秒。所有这些都没有经过time_t
.
这是一个简单的程序,它使用上面的仅 header 库打印出 UTC 时区中的当前日期和时间,精度为 system_clock::time_point
提供(在本例中为微秒):
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
auto const now = system_clock::now();
auto const dp = time_point_cast<days>(now);
auto const date = year_month_day(dp);
auto const time = make_time(now-dp);
cout << date << ' ' << time << " UTC\n";
}
这只是为我输出:
2015-05-19 15:03:47.754002 UTC
这个库有效地变成了 std::chrono::system_clock::time_point
转换为易于使用的日期时间类型。
关于c++ - 如何在不使用 time_t 的情况下将 std::chrono::time_point 转换为 std::tm?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16773285/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!