1 /*
2 	This file is part of Warzone 2100.
3 	Copyright (C) 2020  Warzone 2100 Project
4 
5 	Warzone 2100 is free software; you can redistribute it and/or modify
6 	it under the terms of the GNU General Public License as published by
7 	the Free Software Foundation; either version 2 of the License, or
8 	(at your option) any later version.
9 
10 	Warzone 2100 is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 	GNU General Public License for more details.
14 
15 	You should have received a copy of the GNU General Public License
16 	along with Warzone 2100; if not, write to the Free Software
17 	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 
20 #include "wztime.h"
21 #include <iomanip>
22 #include <sstream>
23 #include "wzglobal.h"
24 #include "frame.h"
25 
getUtcTime(std::time_t const & timer)26 tm getUtcTime(std::time_t const &timer)
27 {
28 	struct tm timeinfo = {};
29 #if defined(WZ_OS_WIN)
30 	if (gmtime_s(&timeinfo, &timer) != 0)
31 	{
32 		// Invalid argument to gmtime_s
33 		debug(LOG_ERROR, "Invalid time_t argument");
34 	}
35 #else
36 	if (!gmtime_r(&timer, &timeinfo))
37 	{
38 		debug(LOG_ERROR, "gmtime_r failed");
39 	}
40 #endif
41 	return timeinfo;
42 }
43 
getLocalTimeOpt(std::time_t const & timer)44 optional<tm> getLocalTimeOpt(std::time_t const &timer)
45 {
46 	struct tm timeinfo = {};
47 #if defined(WZ_OS_WIN)
48 	errno_t result = localtime_s(&timeinfo, &timer);
49 	if (result != 0)
50 	{
51 		char sys_msg[80];
52 		if (strerror_s(sys_msg, sizeof(sys_msg), result) != 0)
53 		{
54 			strncpy(sys_msg, "unknown error", sizeof(sys_msg));
55 		}
56 		debug(LOG_ERROR, "localtime_s failed with error: %s", sys_msg);
57 		return nullopt;
58 	}
59 #else
60 	if (!localtime_r(&timer, &timeinfo))
61 	{
62 		debug(LOG_ERROR, "localtime_r failed");
63 		return nullopt;
64 	}
65 #endif
66 	return timeinfo;
67 }
68 
getLocalTime(std::time_t const & timer)69 tm getLocalTime(std::time_t const &timer)
70 {
71 	auto result = getLocalTimeOpt(timer);
72 	if (!result.has_value())
73 	{
74 		struct tm zeroResult = {};
75 		return zeroResult;
76 	}
77 	return result.value();
78 }
79 
formatLocalDateTime_Internal(char const * format,tm const & tmVal,optional<std::locale> locale=nullopt)80 static std::string const formatLocalDateTime_Internal(char const *format, tm const &tmVal, optional<std::locale> locale = nullopt)
81 {
82 	std::stringstream ss;
83 	if (locale.has_value())
84 	{
85 		ss.imbue(locale.value());
86 	}
87 	ss << std::put_time(&tmVal, format);
88 	return ss.str();
89 }
90 
formatLocalDateTime(char const * format,std::time_t const & timer)91 std::string const formatLocalDateTime(char const *format, std::time_t const &timer)
92 {
93 	auto timeinfo = getLocalTime(timer);
94 	return formatLocalDateTime_Internal(format, timeinfo);
95 }
96 
formatLocalDateTime(char const * format)97 std::string const formatLocalDateTime(char const *format)
98 {
99 	auto timeinfo = getLocalTime(std::time(nullptr));
100 	return formatLocalDateTime_Internal(format, timeinfo);
101 }
102 
getAscTime(tm const & tmVal)103 std::string const getAscTime(tm const &tmVal)
104 {
105 	return formatLocalDateTime_Internal("%c", tmVal, std::locale::classic());
106 }
107