将 posix 时间格式化为仅 3 位小数秒
Format a posix time with just 3 digits in fractional seconds
在以下代码中,microsec_clock
相当于多少毫秒?
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::posix_time::ptime date_time = boost::posix_time::microsec_clock::local_time();
const std::string str_time = boost::posix_time::to_simple_string(date_time);
std::cout << str_time << std::endl;
return 0;
}
output: 2015-Jan-25 16:26:14.932738
我需要以下输出:
output: 2015-Jan-25 16:26:14.932
确实,这似乎是图书馆的一个奇怪遗漏。
话说回来,strftime
好像没有货:http://en.cppreference.com/w/cpp/chrono/c/strftime
那么,如何修补 time_facet
实现才能实现这一点?这是 patch against boost 1.57's boost::date_time::time_facet.hpp
(applied).
1d0
<
39a39
> static const char_type fractional_seconds_3digits[3]; // 3
72a73,76
> time_formats<CharT>::fractional_seconds_3digits[3] = {'%','3'};
>
> template <class CharT>
> const typename time_formats<CharT>::char_type
215a220
> static const char_type* fractional_seconds_3digits; // %3
397a403,411
> if (local_format.find(fractional_seconds_3digits) != string_type::npos) {
> // replace %3 with nnn
> if (frac_str.empty()) {
> frac_str = fractional_seconds_as_3digit_string(time_arg.time_of_day(), false);
> }
> boost::algorithm::replace_all(local_format,
> fractional_seconds_3digits,
> frac_str);
> }
506a521,529
> if (format.find(fractional_seconds_3digits) != string_type::npos) {
> // replace %3 with nnn
> if (frac_str.empty()) {
> frac_str = fractional_seconds_as_3digit_string(time_dur_arg, false);
> }
> boost::algorithm::replace_all(format,
> fractional_seconds_3digits,
> frac_str);
> }
550a574,592
> fractional_seconds_as_3digit_string(const time_duration_type& time_arg,
> bool null_when_zero)
> {
> typename time_duration_type::fractional_seconds_type frac_sec =
> time_arg.fractional_seconds();
>
> for (auto n = time_arg.num_fractional_digits(); n>3; --n)
> frac_sec /= 10;
>
> if (null_when_zero && (frac_sec == 0)) {
> return string_type();
> }
>
> //make sure there is no sign
> return integral_as_string(date_time::absolute_value(frac_sec), 3);
> }
>
> static
> string_type
599a642,645
>
> template <class time_type, class CharT, class OutItrT>
> const typename time_facet<time_type, CharT, OutItrT>::char_type*
> time_facet<time_type, CharT, OutItrT>::fractional_seconds_3digits = time_formats<CharT>::fractional_seconds_3digits;
现在您可以只使用 Boost DateTime 的 time_facet
for ptime
s:
#include "time_facet.hpp"
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
using namespace boost::posix_time;
ptime const date_time = microsec_clock::local_time();
std::cout << date_time << std::endl;
auto facet = new time_facet("%Y-%b-%d %H:%M:%S.%f %z");
std::cout.imbue(std::locale(std::cout.getloc(), facet));
std::cout << date_time << std::endl;
facet = new time_facet("%Y-%b-%d %H:%M:%S.%3 %z");
std::cout.imbue(std::locale(std::cout.getloc(), facet));
std::cout << date_time << std::endl;
}
打印
2015-Jan-25 22:32:30.392108
2015-Jan-25 22:32:30.392108
2015-Jan-25 22:32:30.392
现在这是一个粗略的补丁,只是为了展示如果您要添加它需要完成的工作。相关的改进似乎是:
- 支持允许小数秒中有不同位数的格式字符串
- 使用适当的舍入(而不是截断,现在会发生什么)
希望此示例对您有所帮助。
这是一种打印字符串的方法,比修补 Boost 库 (!!) 更容易一些。关键思想是注意 boost::posix_time::to_simple_string()
如果恰好为零,则不会打印小数部分。所以将小数部分设置为零,使用to_simple_string()
,然后自己手动打印毫秒。
这引出了下一个问题:如何从提升中去除小数部分 ptime
?我发现的最简单的方法(不一定是最简单的方法!)是使用一些绝对参考点通过 time_duration
。为了传统起见,我选择了 1970-01-01,但是你选择什么时间点并不重要(只要它没有小数秒部分!)。
std::string time_with_milli(boost::posix_time::ptime time)
{
using namespace boost::posix_time;
static const ptime epoch(boost::gregorian::date(1900, 1, 1)); // Can be any date
boost::posix_time::time_duration relative_time = time - epoch;
boost::posix_time::ptime date_time_seconds_only =
epoch + boost::posix_time::seconds(relative_time.total_seconds());
uint64_t milliseconds = relative_time.total_milliseconds() % 1000;
std::stringstream ss;
ss << to_simple_string(date_time_seconds_only) << '.'
<< std::setfill('0') << std::setw(3) << milliseconds;
return ss.str();
}
这同样适用于 to_simple_string()
、to_iso_string()
和 to_iso_extended_string()
,尽管 the documentation for them 声称只有 to_simple_string()
省略小数部分,如果它是零。
在以下代码中,microsec_clock
相当于多少毫秒?
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::posix_time::ptime date_time = boost::posix_time::microsec_clock::local_time();
const std::string str_time = boost::posix_time::to_simple_string(date_time);
std::cout << str_time << std::endl;
return 0;
}
output: 2015-Jan-25 16:26:14.932738
我需要以下输出:
output: 2015-Jan-25 16:26:14.932
确实,这似乎是图书馆的一个奇怪遗漏。
话说回来,strftime
好像没有货:http://en.cppreference.com/w/cpp/chrono/c/strftime
那么,如何修补 time_facet
实现才能实现这一点?这是 patch against boost 1.57's boost::date_time::time_facet.hpp
(applied).
1d0
<
39a39
> static const char_type fractional_seconds_3digits[3]; // 3
72a73,76
> time_formats<CharT>::fractional_seconds_3digits[3] = {'%','3'};
>
> template <class CharT>
> const typename time_formats<CharT>::char_type
215a220
> static const char_type* fractional_seconds_3digits; // %3
397a403,411
> if (local_format.find(fractional_seconds_3digits) != string_type::npos) {
> // replace %3 with nnn
> if (frac_str.empty()) {
> frac_str = fractional_seconds_as_3digit_string(time_arg.time_of_day(), false);
> }
> boost::algorithm::replace_all(local_format,
> fractional_seconds_3digits,
> frac_str);
> }
506a521,529
> if (format.find(fractional_seconds_3digits) != string_type::npos) {
> // replace %3 with nnn
> if (frac_str.empty()) {
> frac_str = fractional_seconds_as_3digit_string(time_dur_arg, false);
> }
> boost::algorithm::replace_all(format,
> fractional_seconds_3digits,
> frac_str);
> }
550a574,592
> fractional_seconds_as_3digit_string(const time_duration_type& time_arg,
> bool null_when_zero)
> {
> typename time_duration_type::fractional_seconds_type frac_sec =
> time_arg.fractional_seconds();
>
> for (auto n = time_arg.num_fractional_digits(); n>3; --n)
> frac_sec /= 10;
>
> if (null_when_zero && (frac_sec == 0)) {
> return string_type();
> }
>
> //make sure there is no sign
> return integral_as_string(date_time::absolute_value(frac_sec), 3);
> }
>
> static
> string_type
599a642,645
>
> template <class time_type, class CharT, class OutItrT>
> const typename time_facet<time_type, CharT, OutItrT>::char_type*
> time_facet<time_type, CharT, OutItrT>::fractional_seconds_3digits = time_formats<CharT>::fractional_seconds_3digits;
现在您可以只使用 Boost DateTime 的 time_facet
for ptime
s:
#include "time_facet.hpp"
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
using namespace boost::posix_time;
ptime const date_time = microsec_clock::local_time();
std::cout << date_time << std::endl;
auto facet = new time_facet("%Y-%b-%d %H:%M:%S.%f %z");
std::cout.imbue(std::locale(std::cout.getloc(), facet));
std::cout << date_time << std::endl;
facet = new time_facet("%Y-%b-%d %H:%M:%S.%3 %z");
std::cout.imbue(std::locale(std::cout.getloc(), facet));
std::cout << date_time << std::endl;
}
打印
2015-Jan-25 22:32:30.392108
2015-Jan-25 22:32:30.392108
2015-Jan-25 22:32:30.392
现在这是一个粗略的补丁,只是为了展示如果您要添加它需要完成的工作。相关的改进似乎是:
- 支持允许小数秒中有不同位数的格式字符串
- 使用适当的舍入(而不是截断,现在会发生什么)
希望此示例对您有所帮助。
这是一种打印字符串的方法,比修补 Boost 库 (!!) 更容易一些。关键思想是注意 boost::posix_time::to_simple_string()
如果恰好为零,则不会打印小数部分。所以将小数部分设置为零,使用to_simple_string()
,然后自己手动打印毫秒。
这引出了下一个问题:如何从提升中去除小数部分 ptime
?我发现的最简单的方法(不一定是最简单的方法!)是使用一些绝对参考点通过 time_duration
。为了传统起见,我选择了 1970-01-01,但是你选择什么时间点并不重要(只要它没有小数秒部分!)。
std::string time_with_milli(boost::posix_time::ptime time)
{
using namespace boost::posix_time;
static const ptime epoch(boost::gregorian::date(1900, 1, 1)); // Can be any date
boost::posix_time::time_duration relative_time = time - epoch;
boost::posix_time::ptime date_time_seconds_only =
epoch + boost::posix_time::seconds(relative_time.total_seconds());
uint64_t milliseconds = relative_time.total_milliseconds() % 1000;
std::stringstream ss;
ss << to_simple_string(date_time_seconds_only) << '.'
<< std::setfill('0') << std::setw(3) << milliseconds;
return ss.str();
}
这同样适用于 to_simple_string()
、to_iso_string()
和 to_iso_extended_string()
,尽管 the documentation for them 声称只有 to_simple_string()
省略小数部分,如果它是零。