1570af302Sopenharmony_ci#include <limits.h> 2570af302Sopenharmony_ci#include <stdlib.h> 3570af302Sopenharmony_ci#include <string.h> 4570af302Sopenharmony_ci#include <time.h> 5570af302Sopenharmony_ci#include "test.h" 6570af302Sopenharmony_ci 7570af302Sopenharmony_cistatic char buffer[100]; 8570af302Sopenharmony_ci 9570af302Sopenharmony_cistatic void checkStrftime(const char* format, const struct tm* tm, 10570af302Sopenharmony_ci const char* expected) { 11570af302Sopenharmony_ci size_t resultLength = strftime(buffer, sizeof(buffer), format, tm); 12570af302Sopenharmony_ci 13570af302Sopenharmony_ci if (resultLength != 0 && strcmp(buffer, expected) != 0) { 14570af302Sopenharmony_ci t_error("\"%s\": expected \"%s\", got \"%s\"\n", format, expected, buffer); 15570af302Sopenharmony_ci } else if (resultLength == 0 && strlen(expected) != 0) { 16570af302Sopenharmony_ci t_error("\"%s\": expected \"%s\", got nothing\n", format, expected); 17570af302Sopenharmony_ci } 18570af302Sopenharmony_ci} 19570af302Sopenharmony_ci 20570af302Sopenharmony_cistatic struct tm tm1 = { 21570af302Sopenharmony_ci .tm_sec = 45, 22570af302Sopenharmony_ci .tm_min = 23, 23570af302Sopenharmony_ci .tm_hour = 13, 24570af302Sopenharmony_ci .tm_mday = 3, 25570af302Sopenharmony_ci .tm_mon = 0, 26570af302Sopenharmony_ci .tm_year = 2016 - 1900, 27570af302Sopenharmony_ci .tm_wday = 0, 28570af302Sopenharmony_ci .tm_yday = 2, 29570af302Sopenharmony_ci .tm_isdst = 0 30570af302Sopenharmony_ci}; 31570af302Sopenharmony_ci 32570af302Sopenharmony_cistatic struct tm tm2 = { 33570af302Sopenharmony_ci .tm_sec = 53, 34570af302Sopenharmony_ci .tm_min = 17, 35570af302Sopenharmony_ci .tm_hour = 5, 36570af302Sopenharmony_ci .tm_mday = 5, 37570af302Sopenharmony_ci .tm_mon = 0, 38570af302Sopenharmony_ci .tm_year = 10009 - 1900, 39570af302Sopenharmony_ci .tm_wday = 1, 40570af302Sopenharmony_ci .tm_yday = 4, 41570af302Sopenharmony_ci .tm_isdst = 0 42570af302Sopenharmony_ci}; 43570af302Sopenharmony_ci 44570af302Sopenharmony_cistatic struct tm tm3 = { 45570af302Sopenharmony_ci .tm_sec = 0, 46570af302Sopenharmony_ci .tm_min = 0, 47570af302Sopenharmony_ci .tm_hour = 12, 48570af302Sopenharmony_ci .tm_mday = 23, 49570af302Sopenharmony_ci .tm_mon = 1, 50570af302Sopenharmony_ci .tm_year = 0 - 1900, 51570af302Sopenharmony_ci .tm_wday = 3, 52570af302Sopenharmony_ci .tm_yday = 53, 53570af302Sopenharmony_ci .tm_isdst = 0 54570af302Sopenharmony_ci}; 55570af302Sopenharmony_ci 56570af302Sopenharmony_cistatic struct tm tm4 = { 57570af302Sopenharmony_ci .tm_sec = 0, 58570af302Sopenharmony_ci .tm_min = 0, 59570af302Sopenharmony_ci .tm_hour = 0, 60570af302Sopenharmony_ci .tm_mday = 1, 61570af302Sopenharmony_ci .tm_mon = 0, 62570af302Sopenharmony_ci .tm_year = -123 - 1900, 63570af302Sopenharmony_ci .tm_wday = 1, 64570af302Sopenharmony_ci .tm_yday = 0, 65570af302Sopenharmony_ci .tm_isdst = 0 66570af302Sopenharmony_ci}; 67570af302Sopenharmony_ci 68570af302Sopenharmony_cistatic struct tm tm5 = { 69570af302Sopenharmony_ci .tm_sec = 0, 70570af302Sopenharmony_ci .tm_min = 0, 71570af302Sopenharmony_ci .tm_hour = 0, 72570af302Sopenharmony_ci .tm_mday = 1, 73570af302Sopenharmony_ci .tm_mon = 0, 74570af302Sopenharmony_ci .tm_year = INT_MAX, 75570af302Sopenharmony_ci .tm_wday = 3, 76570af302Sopenharmony_ci .tm_yday = 0, 77570af302Sopenharmony_ci .tm_isdst = 0 78570af302Sopenharmony_ci}; 79570af302Sopenharmony_ci 80570af302Sopenharmony_ciint main() { 81570af302Sopenharmony_ci setenv("TZ", "UTC0", 1); 82570af302Sopenharmony_ci 83570af302Sopenharmony_ci checkStrftime("%c", &tm1, "Sun Jan 3 13:23:45 2016"); 84570af302Sopenharmony_ci checkStrftime("%c", &tm2, "Mon Jan 5 05:17:53 +10009"); 85570af302Sopenharmony_ci checkStrftime("%c", &tm3, "Wed Feb 23 12:00:00 0000"); 86570af302Sopenharmony_ci 87570af302Sopenharmony_ci // The POSIX.1-2008 standard does not specify the padding character for 88570af302Sopenharmony_ci // "%C". The C standard requires that the number is padded by '0'. 89570af302Sopenharmony_ci // See also http://austingroupbugs.net/view.php?id=1184 90570af302Sopenharmony_ci checkStrftime("%C", &tm1, "20"); 91570af302Sopenharmony_ci checkStrftime("%03C", &tm1, "020"); 92570af302Sopenharmony_ci checkStrftime("%+3C", &tm1, "+20"); 93570af302Sopenharmony_ci checkStrftime("%C", &tm2, "100"); 94570af302Sopenharmony_ci checkStrftime("%C", &tm3, "00"); 95570af302Sopenharmony_ci checkStrftime("%01C", &tm3, "0"); 96570af302Sopenharmony_ci 97570af302Sopenharmony_ci checkStrftime("%F", &tm1, "2016-01-03"); 98570af302Sopenharmony_ci checkStrftime("%012F", &tm1, "002016-01-03"); 99570af302Sopenharmony_ci checkStrftime("%+10F", &tm1, "2016-01-03"); 100570af302Sopenharmony_ci checkStrftime("%+11F", &tm1, "+2016-01-03"); 101570af302Sopenharmony_ci checkStrftime("%F", &tm2, "+10009-01-05"); 102570af302Sopenharmony_ci checkStrftime("%011F", &tm2, "10009-01-05"); 103570af302Sopenharmony_ci checkStrftime("%F", &tm3, "0000-02-23"); 104570af302Sopenharmony_ci checkStrftime("%01F", &tm3, "0-02-23"); 105570af302Sopenharmony_ci checkStrftime("%06F", &tm3, "0-02-23"); 106570af302Sopenharmony_ci checkStrftime("%010F", &tm3, "0000-02-23"); 107570af302Sopenharmony_ci checkStrftime("%F", &tm4, "-123-01-01"); 108570af302Sopenharmony_ci checkStrftime("%011F", &tm4, "-0123-01-01"); 109570af302Sopenharmony_ci 110570af302Sopenharmony_ci checkStrftime("%g", &tm1, "15"); 111570af302Sopenharmony_ci checkStrftime("%g", &tm2, "09"); 112570af302Sopenharmony_ci 113570af302Sopenharmony_ci checkStrftime("%G", &tm1, "2015"); 114570af302Sopenharmony_ci checkStrftime("%+5G", &tm1, "+2015"); 115570af302Sopenharmony_ci checkStrftime("%04G", &tm2, "10009"); 116570af302Sopenharmony_ci 117570af302Sopenharmony_ci checkStrftime("%r", &tm1, "01:23:45 PM"); 118570af302Sopenharmony_ci checkStrftime("%r", &tm2, "05:17:53 AM"); 119570af302Sopenharmony_ci checkStrftime("%r", &tm3, "12:00:00 PM"); 120570af302Sopenharmony_ci checkStrftime("%r", &tm4, "12:00:00 AM"); 121570af302Sopenharmony_ci 122570af302Sopenharmony_ci // The "%s" specifier was accepted by the Austin Group for the next POSIX.1 123570af302Sopenharmony_ci // revision. See http://austingroupbugs.net/view.php?id=169 124570af302Sopenharmony_ci checkStrftime("%s", &tm1, "1451827425"); 125570af302Sopenharmony_ci if (sizeof(time_t) * CHAR_BIT >= 64) { 126570af302Sopenharmony_ci checkStrftime("%s", &tm2, "253686748673"); 127570af302Sopenharmony_ci } 128570af302Sopenharmony_ci 129570af302Sopenharmony_ci checkStrftime("%T", &tm1, "13:23:45"); 130570af302Sopenharmony_ci checkStrftime("%T", &tm2, "05:17:53"); 131570af302Sopenharmony_ci checkStrftime("%T", &tm3, "12:00:00"); 132570af302Sopenharmony_ci checkStrftime("%T", &tm4, "00:00:00"); 133570af302Sopenharmony_ci 134570af302Sopenharmony_ci checkStrftime("%U", &tm1, "01"); 135570af302Sopenharmony_ci checkStrftime("%U", &tm2, "01"); 136570af302Sopenharmony_ci checkStrftime("%U", &tm3, "08"); 137570af302Sopenharmony_ci 138570af302Sopenharmony_ci checkStrftime("%V", &tm1, "53"); 139570af302Sopenharmony_ci checkStrftime("%V", &tm2, "02"); 140570af302Sopenharmony_ci checkStrftime("%V", &tm3, "08"); 141570af302Sopenharmony_ci 142570af302Sopenharmony_ci checkStrftime("%W", &tm1, "00"); 143570af302Sopenharmony_ci checkStrftime("%W", &tm2, "01"); 144570af302Sopenharmony_ci checkStrftime("%W", &tm3, "08"); 145570af302Sopenharmony_ci 146570af302Sopenharmony_ci checkStrftime("%x", &tm1, "01/03/16"); 147570af302Sopenharmony_ci checkStrftime("%X", &tm1, "13:23:45"); 148570af302Sopenharmony_ci checkStrftime("%y", &tm1, "16"); 149570af302Sopenharmony_ci 150570af302Sopenharmony_ci // There is no standard that explicitly specifies the exact format of "%Y". 151570af302Sopenharmony_ci // The C standard says that "%F" is equivalent to "%Y-%m-%d". The 152570af302Sopenharmony_ci // POSIX.1-2008 standard says that "%F" is equivalent to "%+4Y-%m-%d". 153570af302Sopenharmony_ci // This implies that to conform to both standards "%Y" needs to be 154570af302Sopenharmony_ci // equivalent to "%+4Y". 155570af302Sopenharmony_ci // See also http://austingroupbugs.net/view.php?id=739 156570af302Sopenharmony_ci checkStrftime("%Y", &tm1, "2016"); 157570af302Sopenharmony_ci checkStrftime("%05Y", &tm1, "02016"); 158570af302Sopenharmony_ci checkStrftime("%+4Y", &tm1, "2016"); 159570af302Sopenharmony_ci checkStrftime("%+5Y", &tm1, "+2016"); 160570af302Sopenharmony_ci checkStrftime("%Y", &tm2, "+10009"); 161570af302Sopenharmony_ci checkStrftime("%05Y", &tm2, "10009"); 162570af302Sopenharmony_ci checkStrftime("%Y", &tm3, "0000"); 163570af302Sopenharmony_ci checkStrftime("%02Y", &tm3, "00"); 164570af302Sopenharmony_ci checkStrftime("%+5Y", &tm3, "+0000"); 165570af302Sopenharmony_ci checkStrftime("%Y", &tm4, "-123"); 166570af302Sopenharmony_ci checkStrftime("%+4Y", &tm4, "-123"); 167570af302Sopenharmony_ci checkStrftime("%+5Y", &tm4, "-0123"); 168570af302Sopenharmony_ci 169570af302Sopenharmony_ci if (INT_MAX == 0x7FFFFFFF) { 170570af302Sopenharmony_ci // The standard does not specify any range for tm_year, so INT_MAX 171570af302Sopenharmony_ci // should be valid. 172570af302Sopenharmony_ci checkStrftime("%y", &tm5, "47"); 173570af302Sopenharmony_ci checkStrftime("%Y", &tm5, "+2147485547"); 174570af302Sopenharmony_ci checkStrftime("%011Y", &tm5, "02147485547"); 175570af302Sopenharmony_ci if (sizeof(time_t) * CHAR_BIT >= 64) { 176570af302Sopenharmony_ci checkStrftime("%s", &tm5, "67768036160140800"); 177570af302Sopenharmony_ci } 178570af302Sopenharmony_ci } 179570af302Sopenharmony_ci 180570af302Sopenharmony_ci return t_status; 181570af302Sopenharmony_ci} 182