diff options
author | howar6hill <f.eiwu@yahoo.com> | 2020-03-08 18:35:26 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-08 11:35:26 +0100 |
commit | 10e0d4a196a1d70e35af8c011f814033a5f5e269 (patch) | |
tree | 8a5ee345569f31bee44504b4e54da478f1089b4c | |
parent | b6307beb6ef581584603f92b2ce4af1382fff646 (diff) | |
download | serenity-10e0d4a196a1d70e35af8c011f814033a5f5e269.zip |
LibCore: Add format option for DateTime::to_string() (#1358)
-rw-r--r-- | Libraries/LibCore/DateTime.cpp | 149 | ||||
-rw-r--r-- | Libraries/LibCore/DateTime.h | 4 |
2 files changed, 148 insertions, 5 deletions
diff --git a/Libraries/LibCore/DateTime.cpp b/Libraries/LibCore/DateTime.cpp index e0ace57089..1836c2d6a7 100644 --- a/Libraries/LibCore/DateTime.cpp +++ b/Libraries/LibCore/DateTime.cpp @@ -24,7 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <AK/String.h> +#include <AK/StringBuilder.h> #include <LibCore/DateTime.h> #include <sys/time.h> #include <time.h> @@ -51,9 +51,152 @@ DateTime DateTime::from_timestamp(time_t timestamp) return dt; } -String DateTime::to_string() const +String DateTime::to_string(const String& format) const { - return String::format("%04u-%02u-%02u %02u:%02u:%02u", m_year, m_month, m_day, m_hour, m_minute, m_second); + + const char wday_short_names[7][4] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + const char wday_long_names[7][10] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + }; + const char mon_short_names[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + const char mon_long_names[12][10] = { + "January", "February", "March", "April", "May", "June", + "July", "Auguest", "September", "October", "November", "December" + }; + + struct tm tm; + localtime_r(&m_timestamp, &tm); + StringBuilder builder; + const int format_len = format.length(); + + for (int i = 0; i < format_len; ++i) { + if (format[i] != '%') { + builder.append(format[i]); + } else { + if (++i == format_len) + return String(); + + switch (format[i]) { + case 'a': + builder.append(wday_short_names[tm.tm_wday]); + break; + case 'A': + builder.append(wday_long_names[tm.tm_wday]); + break; + case 'b': + builder.append(mon_short_names[tm.tm_mon]); + break; + case 'B': + builder.append(mon_long_names[tm.tm_mon]); + break; + case 'C': + builder.appendf("%02d", (tm.tm_year + 1900) / 100); + break; + case 'd': + builder.appendf("%02d", tm.tm_mday); + break; + case 'D': + builder.appendf("%02d/%02d/%02d", tm.tm_mon + 1, tm.tm_mday, (tm.tm_year + 1900) % 100); + break; + case 'e': + builder.appendf("%2d", tm.tm_mday); + break; + case 'h': + builder.append(mon_short_names[tm.tm_mon]); + break; + case 'H': + builder.appendf("%02d", tm.tm_hour); + break; + case 'I': + builder.appendf("%02d", tm.tm_hour % 12); + break; + case 'j': + builder.appendf("%03d", tm.tm_yday + 1); + break; + case 'm': + builder.appendf("%02d", tm.tm_mon + 1); + break; + case 'M': + builder.appendf("%02d", tm.tm_min); + break; + case 'n': + builder.append('\n'); + break; + case 'p': + builder.append(tm.tm_hour < 12 ? "a.m." : "p.m."); + break; + case 'r': + builder.appendf("%02d:%02d:%02d %s", tm.tm_hour % 12, tm.tm_min, tm.tm_sec, tm.tm_hour < 12 ? "a.m." : "p.m."); + break; + case 'R': + builder.appendf("%02d:%02d", tm.tm_hour, tm.tm_min); + break; + case 'S': + builder.appendf("%02d", tm.tm_sec); + break; + case 't': + builder.append('\t'); + break; + case 'T': + builder.appendf("%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec); + break; + case 'u': + builder.appendf("%d", tm.tm_wday ? tm.tm_wday : 7); + break; + case 'U': { + const int wday_of_year_beginning = (tm.tm_wday + 6 * tm.tm_yday) % 7; + const int week_number = (tm.tm_yday + wday_of_year_beginning) / 7; + builder.appendf("%02d", week_number); + break; + } + case 'V': { + const int wday_of_year_beginning = (tm.tm_wday + 6 + 6 * tm.tm_yday) % 7; + int week_number = (tm.tm_yday + wday_of_year_beginning) / 7 + 1; + if (wday_of_year_beginning > 3) { + if (tm.tm_yday >= 7 - wday_of_year_beginning) + --week_number; + else { + const bool last_year_is_leap = ((tm.tm_year + 1900 - 1) % 4 == 0 && (tm.tm_year + 1900 - 1) % 100 != 0) || (tm.tm_year + 1900 - 1) % 400 == 0; + const int days_of_last_year = 365 + last_year_is_leap; + const int wday_of_last_year_beginning = (wday_of_year_beginning + 6 * days_of_last_year) % 7; + week_number = (days_of_last_year + wday_of_last_year_beginning) / 7 + 1; + if (wday_of_last_year_beginning > 3) + --week_number; + } + } + builder.appendf("%02d", week_number); + break; + } + case 'w': + builder.appendf("%d", tm.tm_wday); + break; + case 'W': { + const int wday_of_year_beginning = (tm.tm_wday + 6 + 6 * tm.tm_yday) % 7; + const int week_number = (tm.tm_yday + wday_of_year_beginning) / 7; + builder.appendf("%02d", week_number); + break; + } + case 'y': + builder.appendf("%02d", (tm.tm_year + 1900) % 100); + break; + case 'Y': + builder.appendf("%d", tm.tm_year + 1900); + break; + case '%': + builder.append('%'); + break; + default: + return String(); + } + } + } + + return builder.build(); } const LogStream& operator<<(const LogStream& stream, const DateTime& value) diff --git a/Libraries/LibCore/DateTime.h b/Libraries/LibCore/DateTime.h index a27a04c2d9..56a9b17680 100644 --- a/Libraries/LibCore/DateTime.h +++ b/Libraries/LibCore/DateTime.h @@ -26,7 +26,7 @@ #pragma once -#include <AK/Forward.h> +#include <AK/String.h> #include <time.h> namespace Core { @@ -43,7 +43,7 @@ public: unsigned minute() const { return m_minute; } unsigned second() const { return m_second; } - String to_string() const; + String to_string(const String& format = "%Y-%m-%d %H:%M:%S") const; static DateTime now(); static DateTime from_timestamp(time_t); |