Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions fmt/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
#include "fmt/format.h"
#include <ctime>

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4702) // unreachable code
#pragma warning(disable: 4996) // "deprecated" functions
#endif

namespace fmt {
template <typename ArgFormatter>
void format_arg(BasicFormatter<char, ArgFormatter> &f,
Expand Down Expand Up @@ -48,6 +54,99 @@ void format_arg(BasicFormatter<char, ArgFormatter> &f,
}
format_str = end + 1;
}

namespace internal{
inline Null<> localtime_r(...){
return Null<>();
}
inline Null<> localtime_s(...){
return Null<>();
}
inline Null<> gmtime_r(...){
return Null<>();
}
inline Null<> gmtime_s(...){
return Null<>();
}
}

// Thread-safe replacement for std::localtime
inline std::tm localtime(std::time_t time){
struct LocalTime {
std::time_t time_;
std::tm tm_;

LocalTime(std::time_t t)
:time_(t) {}
bool run(){
using namespace fmt::internal;
return handle(localtime_r(&time_, &tm_));
}
bool handle(std::tm* tm){
return tm != 0;
}
bool handle(internal::Null<>){
using namespace fmt::internal;
return fallback(localtime_s(&tm_, &time_));
}
bool fallback(int res){
return res == 0;
}
bool fallback(internal::Null<>){
using namespace fmt::internal;
std::tm* tm = std::localtime(&time_);
if (tm != 0) tm_ = *tm;
return tm != 0;
}
};
LocalTime lt(time);
if (lt.run())
return lt.tm_;
// Too big time values may be unsupported
FMT_THROW(fmt::FormatError("time_t value out of range"));
return std::tm();
}

// Thread-safe replacement for std::gmtime
inline std::tm gmtime(std::time_t time)
{
struct GmTime {
std::time_t time_;
std::tm tm_;

GmTime(std::time_t t)
:time_(t) {}
bool run(){
using namespace fmt::internal;
return handle(gmtime_r(&time_, &tm_));
}
bool handle(std::tm* tm){
return tm != 0;
}
bool handle(internal::Null<>){
using namespace fmt::internal;
return fallback(gmtime_s(&tm_, &time_));
}
bool fallback(int res){
return res == 0;
}
bool fallback(internal::Null<>){
std::tm* tm = std::gmtime(&time_);
if (tm != 0) tm_ = *tm;
return tm != 0;
}
};
GmTime gt(time);
if (gt.run())
return gt.tm_;
// Too big time values may be unsupported
FMT_THROW(fmt::FormatError("time_t value out of range"));
return std::tm();
}
} //namespace fmt

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#endif // FMT_TIME_H_