1 /* 2 ************************************************************************* 3 * 2016 and later: Unicode, Inc. and others. 4 * License & terms of use: http://www.unicode.org/copyright.html#License 5 ************************************************************************* 6 *********************************************************************** 7 * Copyright (C) 1998-2012, International Business Machines 8 * Corporation and others. All Rights Reserved. 9 ********************************************************************** 10 * 11 * File date.c 12 * 13 * Modification History: 14 * 15 * Date Name Description 16 * 06/11/99 stephen Creation. 17 * 06/16/99 stephen Modified to use uprint. 18 * 08/11/11 srl added Parse and milli/second in/out 19 ******************************************************************************* 20 */ 21 22 #include <stdlib.h> 23 #include <stdio.h> 24 #include <string.h> 25 26 #include "unicode/utypes.h" 27 #include "unicode/ustring.h" 28 #include "unicode/uclean.h" 29 30 #include "unicode/ucnv.h" 31 #include "unicode/udat.h" 32 #include "unicode/ucal.h" 33 34 #include "uprint.h" 35 36 int main(int argc, char **argv); 37 38 #if UCONFIG_NO_FORMATTING || UCONFIG_NO_CONVERSION 39 40 int main(int argc, char **argv) 41 { 42 printf("%s: Sorry, UCONFIG_NO_FORMATTING or UCONFIG_NO_CONVERSION was turned on (see uconfig.h). No formatting can be done. \n", argv[0]); 43 return 0; 44 } 45 #else 46 47 48 /* Protos */ 49 static void usage(void); 50 static void version(void); 51 static void date(UDate when, const UChar *tz, UDateFormatStyle style, const char *format, const char *locale, UErrorCode *status); 52 static UDate getWhen(const char *millis, const char *seconds, const char *format, const char *locale, UDateFormatStyle style, const char *parse, const UChar *tz, UErrorCode *status); 53 54 UConverter *cnv = NULL; 55 56 /* The version of date */ 57 #define DATE_VERSION "1.0" 58 59 /* "GMT" */ 60 static const UChar GMT_ID [] = { 0x0047, 0x004d, 0x0054, 0x0000 }; 61 62 #define FORMAT_MILLIS "%" 63 #define FORMAT_SECONDS "%%" 64 65 int 66 main(int argc, 67 char **argv) 68 { 69 int printUsage = 0; 70 int printVersion = 0; 71 int optInd = 1; 72 char *arg; 73 const UChar *tz = 0; 74 UDateFormatStyle style = UDAT_DEFAULT; 75 UErrorCode status = U_ZERO_ERROR; 76 const char *format = NULL; 77 const char *locale = NULL; 78 char *parse = NULL; 79 char *seconds = NULL; 80 char *millis = NULL; 81 UDate when; 82 83 /* parse the options */ 84 for(optInd = 1; optInd < argc; ++optInd) { 85 arg = argv[optInd]; 86 87 /* version info */ 88 if(strcmp(arg, "-v") == 0 || strcmp(arg, "--version") == 0) { 89 printVersion = 1; 90 } 91 /* usage info */ 92 else if(strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { 93 printUsage = 1; 94 } 95 /* display date in gmt */ 96 else if(strcmp(arg, "-u") == 0 || strcmp(arg, "--gmt") == 0) { 97 tz = GMT_ID; 98 } 99 /* display date in gmt */ 100 else if(strcmp(arg, "-f") == 0 || strcmp(arg, "--full") == 0) { 101 style = UDAT_FULL; 102 } 103 /* display date in long format */ 104 else if(strcmp(arg, "-l") == 0 || strcmp(arg, "--long") == 0) { 105 style = UDAT_LONG; 106 } 107 /* display date in medium format */ 108 else if(strcmp(arg, "-m") == 0 || strcmp(arg, "--medium") == 0) { 109 style = UDAT_MEDIUM; 110 } 111 /* display date in short format */ 112 else if(strcmp(arg, "-s") == 0 || strcmp(arg, "--short") == 0) { 113 style = UDAT_SHORT; 114 } 115 else if(strcmp(arg, "-F") == 0 || strcmp(arg, "--format") == 0) { 116 if ( optInd + 1 < argc ) { 117 optInd++; 118 format = argv[optInd]; 119 } 120 } else if(strcmp(arg, "-r") == 0) { 121 if ( optInd + 1 < argc ) { 122 optInd++; 123 seconds = argv[optInd]; 124 } 125 } else if(strcmp(arg, "-R") == 0) { 126 if ( optInd + 1 < argc ) { 127 optInd++; 128 millis = argv[optInd]; 129 } 130 } else if(strcmp(arg, "-P") == 0) { 131 if ( optInd + 1 < argc ) { 132 optInd++; 133 parse = argv[optInd]; 134 } 135 } 136 else if (strcmp(arg, "-L") == 0) { 137 if (optInd + 1 < argc) { 138 optInd++; 139 locale = argv[optInd]; 140 } 141 } 142 /* POSIX.1 says all arguments after -- are not options */ 143 else if(strcmp(arg, "--") == 0) { 144 /* skip the -- */ 145 ++optInd; 146 break; 147 } 148 /* unrecognized option */ 149 else if(strncmp(arg, "-", strlen("-")) == 0) { 150 printf("icudate: invalid option -- %s\n", arg+1); 151 printUsage = 1; 152 } 153 /* done with options, display date */ 154 else { 155 break; 156 } 157 } 158 159 /* print usage info */ 160 if(printUsage) { 161 usage(); 162 return 0; 163 } 164 165 /* print version info */ 166 if(printVersion) { 167 version(); 168 return 0; 169 } 170 171 /* get the 'when' (or now) */ 172 when = getWhen(millis, seconds, format, locale, style, parse, tz, &status); 173 if(parse != NULL) { 174 format = FORMAT_MILLIS; /* output in millis */ 175 } 176 177 /* print the date */ 178 date(when, tz, style, format, locale, &status); 179 180 ucnv_close(cnv); 181 182 u_cleanup(); 183 return (U_FAILURE(status) ? 1 : 0); 184 } 185 186 /* Usage information */ 187 static void 188 usage() 189 { 190 puts("Usage: icudate [OPTIONS]"); 191 puts("Options:"); 192 puts(" -h, --help Print this message and exit."); 193 puts(" -v, --version Print the version number of date and exit."); 194 puts(" -u, --gmt Display the date in Greenwich Mean Time."); 195 puts(" -f, --full Use full display format."); 196 puts(" -l, --long Use long display format."); 197 puts(" -m, --medium Use medium display format."); 198 puts(" -s, --short Use short display format."); 199 puts(" -F <format>, --format <format> Use <format> as the display format."); 200 puts(" (Special formats: \"%\" alone is Millis since 1970, \"%%\" alone is Seconds since 1970)"); 201 puts(" -r <seconds> Use <seconds> as the time (Epoch 1970) rather than now."); 202 puts(" -R <millis> Use <millis> as the time (Epoch 1970) rather than now."); 203 puts(" -P <string> Parse <string> as the time, output in millis format."); 204 puts(" -L <string> Use the locale <string> instead of the default ICU locale."); 205 } 206 207 /* Version information */ 208 static void 209 version() 210 { 211 UErrorCode status = U_ZERO_ERROR; 212 const char *tzVer; 213 int len = 256; 214 UChar tzName[256]; 215 printf("icudate version %s, created by Stephen F. Booth.\n", 216 DATE_VERSION); 217 puts(U_COPYRIGHT_STRING); 218 tzVer = ucal_getTZDataVersion(&status); 219 if(U_FAILURE(status)) { 220 tzVer = u_errorName(status); 221 } 222 printf("\n"); 223 printf("ICU Version: %s\n", U_ICU_VERSION); 224 printf("ICU Data (major+min): %s\n", U_ICUDATA_NAME); 225 printf("Default Locale: %s\n", uloc_getDefault()); 226 printf("Time Zone Data Version: %s\n", tzVer); 227 printf("Default Time Zone: "); 228 status = U_ZERO_ERROR; 229 u_init(&status); 230 len = ucal_getDefaultTimeZone(tzName, len, &status); 231 if(U_FAILURE(status)) { 232 fprintf(stderr, " ** Error getting default zone: %s\n", u_errorName(status)); 233 } 234 uprint(tzName, stdout, &status); 235 printf("\n\n"); 236 } 237 238 static int32_t charsToUCharsDefault(UChar *uchars, int32_t ucharsSize, const char*chars, int32_t charsSize, UErrorCode *status) { 239 int32_t len=-1; 240 if(U_FAILURE(*status)) return len; 241 if(cnv==NULL) { 242 cnv = ucnv_open(NULL, status); 243 } 244 if(cnv&&U_SUCCESS(*status)) { 245 len = ucnv_toUChars(cnv, uchars, ucharsSize, chars,charsSize, status); 246 } 247 return len; 248 } 249 250 /* Format the date */ 251 static void 252 date(UDate when, 253 const UChar *tz, 254 UDateFormatStyle style, 255 const char *format, 256 const char *locale, 257 UErrorCode *status ) 258 { 259 UChar *s = 0; 260 int32_t len = 0; 261 UDateFormat *fmt; 262 UChar uFormat[100]; 263 264 if(U_FAILURE(*status)) return; 265 266 if( format != NULL ) { 267 if(!strcmp(format,FORMAT_MILLIS)) { 268 printf("%.0f\n", when); 269 return; 270 } else if(!strcmp(format, FORMAT_SECONDS)) { 271 printf("%.3f\n", when/1000.0); 272 return; 273 } 274 } 275 276 fmt = udat_open(style, style, locale, tz, -1,NULL,0, status); 277 if ( format != NULL ) { 278 charsToUCharsDefault(uFormat,sizeof(uFormat)/sizeof(uFormat[0]),format,-1,status); 279 udat_applyPattern(fmt,FALSE,uFormat,-1); 280 } 281 len = udat_format(fmt, when, 0, len, 0, status); 282 if(*status == U_BUFFER_OVERFLOW_ERROR) { 283 *status = U_ZERO_ERROR; 284 s = (UChar*) malloc(sizeof(UChar) * (len+1)); 285 if(s == 0) goto finish; 286 udat_format(fmt, when, s, len + 1, 0, status); 287 } 288 if(U_FAILURE(*status)) goto finish; 289 290 /* print the date string */ 291 uprint(s, stdout, status); 292 293 /* print a trailing newline */ 294 printf("\n"); 295 296 finish: 297 if(U_FAILURE(*status)) { 298 fprintf(stderr, "Error in Print: %s\n", u_errorName(*status)); 299 } 300 udat_close(fmt); 301 free(s); 302 } 303 304 static UDate getWhen(const char *millis, const char *seconds, const char *format, const char *locale, 305 UDateFormatStyle style, const char *parse, const UChar *tz, UErrorCode *status) { 306 UDateFormat *fmt = NULL; 307 UChar uFormat[100]; 308 UChar uParse[256]; 309 UDate when=0; 310 int32_t parsepos = 0; 311 312 if(millis != NULL) { 313 sscanf(millis, "%lf", &when); 314 return when; 315 } else if(seconds != NULL) { 316 sscanf(seconds, "%lf", &when); 317 return when*1000.0; 318 } 319 320 if(parse!=NULL) { 321 if( format != NULL ) { 322 if(!strcmp(format,FORMAT_MILLIS)) { 323 sscanf(parse, "%lf", &when); 324 return when; 325 } else if(!strcmp(format, FORMAT_SECONDS)) { 326 sscanf(parse, "%lf", &when); 327 return when*1000.0; 328 } 329 } 330 331 fmt = udat_open(style, style, locale, tz, -1,NULL,0, status); 332 if ( format != NULL ) { 333 charsToUCharsDefault(uFormat,sizeof(uFormat)/sizeof(uFormat[0]), format,-1,status); 334 udat_applyPattern(fmt,FALSE,uFormat,-1); 335 } 336 337 charsToUCharsDefault(uParse,sizeof(uParse)/sizeof(uParse[0]), parse,-1,status); 338 when = udat_parse(fmt, uParse, -1, &parsepos, status); 339 if(U_FAILURE(*status)) { 340 fprintf(stderr, "Error in Parse: %s\n", u_errorName(*status)); 341 if(parsepos > 0 && parsepos <= (int32_t)strlen(parse)) { 342 fprintf(stderr, "ERR>\"%s\" @%d\n" 343 "ERR> %*s^\n", 344 parse,parsepos,parsepos,""); 345 346 } 347 } 348 349 udat_close(fmt); 350 return when; 351 } else { 352 return ucal_getNow(); 353 } 354 } 355 356 #endif 357