1 /*
2 *************************************************************************
3 *   Copyright (C) 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 
main(int argc,char ** argv)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, UErrorCode *status);
52 static UDate getWhen(const char *millis, const char *seconds, const char *format, 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
main(int argc,char ** argv)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   char *parse = NULL;
78   char *seconds = NULL;
79   char *millis = NULL;
80   UDate when;
81 
82   /* parse the options */
83   for(optInd = 1; optInd < argc; ++optInd) {
84     arg = argv[optInd];
85 
86     /* version info */
87     if(strcmp(arg, "-v") == 0 || strcmp(arg, "--version") == 0) {
88       printVersion = 1;
89     }
90     /* usage info */
91     else if(strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
92       printUsage = 1;
93     }
94     /* display date in gmt */
95     else if(strcmp(arg, "-u") == 0 || strcmp(arg, "--gmt") == 0) {
96       tz = GMT_ID;
97     }
98     /* display date in gmt */
99     else if(strcmp(arg, "-f") == 0 || strcmp(arg, "--full") == 0) {
100       style = UDAT_FULL;
101     }
102     /* display date in long format */
103     else if(strcmp(arg, "-l") == 0 || strcmp(arg, "--long") == 0) {
104       style = UDAT_LONG;
105     }
106     /* display date in medium format */
107     else if(strcmp(arg, "-m") == 0 || strcmp(arg, "--medium") == 0) {
108       style = UDAT_MEDIUM;
109     }
110     /* display date in short format */
111     else if(strcmp(arg, "-s") == 0 || strcmp(arg, "--short") == 0) {
112       style = UDAT_SHORT;
113     }
114     else if(strcmp(arg, "-F") == 0 || strcmp(arg, "--format") == 0) {
115       if ( optInd + 1 < argc ) {
116          optInd++;
117          format = argv[optInd];
118       }
119     } else if(strcmp(arg, "-r") == 0) {
120       if ( optInd + 1 < argc ) {
121          optInd++;
122          seconds = argv[optInd];
123       }
124     } else if(strcmp(arg, "-R") == 0) {
125       if ( optInd + 1 < argc ) {
126          optInd++;
127          millis = argv[optInd];
128       }
129     } else if(strcmp(arg, "-P") == 0) {
130       if ( optInd + 1 < argc ) {
131          optInd++;
132          parse = argv[optInd];
133       }
134     }
135     /* POSIX.1 says all arguments after -- are not options */
136     else if(strcmp(arg, "--") == 0) {
137       /* skip the -- */
138       ++optInd;
139       break;
140     }
141     /* unrecognized option */
142     else if(strncmp(arg, "-", strlen("-")) == 0) {
143       printf("icudate: invalid option -- %s\n", arg+1);
144       printUsage = 1;
145     }
146     /* done with options, display date */
147     else {
148       break;
149     }
150   }
151 
152   /* print usage info */
153   if(printUsage) {
154     usage();
155     return 0;
156   }
157 
158   /* print version info */
159   if(printVersion) {
160     version();
161     return 0;
162   }
163 
164   /* get the 'when' (or now) */
165   when = getWhen(millis, seconds, format, style, parse, tz, &status);
166   if(parse != NULL) {
167     format = FORMAT_MILLIS; /* output in millis */
168   }
169 
170   /* print the date */
171   date(when, tz, style, format, &status);
172 
173   ucnv_close(cnv);
174 
175   u_cleanup();
176   return (U_FAILURE(status) ? 1 : 0);
177 }
178 
179 /* Usage information */
180 static void
usage()181 usage()
182 {
183   puts("Usage: icudate [OPTIONS]");
184   puts("Options:");
185   puts("  -h, --help        Print this message and exit.");
186   puts("  -v, --version     Print the version number of date and exit.");
187   puts("  -u, --gmt         Display the date in Greenwich Mean Time.");
188   puts("  -f, --full        Use full display format.");
189   puts("  -l, --long        Use long display format.");
190   puts("  -m, --medium      Use medium display format.");
191   puts("  -s, --short       Use short display format.");
192   puts("  -F <format>, --format <format>       Use <format> as the display format.");
193   puts("                    (Special formats: \"%\" alone is Millis since 1970, \"%%\" alone is Seconds since 1970)");
194   puts("  -r <seconds>      Use <seconds> as the time (Epoch 1970) rather than now.");
195   puts("  -R <millis>       Use <millis> as the time (Epoch 1970) rather than now.");
196   puts("  -P <string>       Parse <string> as the time, output in millis format.");
197 }
198 
199 /* Version information */
200 static void
version()201 version()
202 {
203   UErrorCode status = U_ZERO_ERROR;
204   const char *tzVer;
205   int len = 256;
206   UChar tzName[256];
207   printf("icudate version %s, created by Stephen F. Booth.\n",
208 	 DATE_VERSION);
209   puts(U_COPYRIGHT_STRING);
210   tzVer = ucal_getTZDataVersion(&status);
211   if(U_FAILURE(status)) {
212       tzVer = u_errorName(status);
213   }
214   printf("\n");
215   printf("ICU Version:               %s\n", U_ICU_VERSION);
216   printf("ICU Data (major+min):      %s\n", U_ICUDATA_NAME);
217   printf("Default Locale:            %s\n", uloc_getDefault());
218   printf("Time Zone Data Version:    %s\n", tzVer);
219   printf("Default Time Zone:         ");
220   status = U_ZERO_ERROR;
221   u_init(&status);
222   len = ucal_getDefaultTimeZone(tzName, len, &status);
223   if(U_FAILURE(status)) {
224     fprintf(stderr, " ** Error getting default zone: %s\n", u_errorName(status));
225   }
226   uprint(tzName, stdout, &status);
227   printf("\n\n");
228 }
229 
charsToUCharsDefault(UChar * uchars,int32_t ucharsSize,const char * chars,int32_t charsSize,UErrorCode * status)230 static int32_t charsToUCharsDefault(UChar *uchars, int32_t ucharsSize, const char*chars, int32_t charsSize, UErrorCode *status) {
231   int32_t len=-1;
232   if(U_FAILURE(*status)) return len;
233   if(cnv==NULL) {
234     cnv = ucnv_open(NULL, status);
235   }
236   if(cnv&&U_SUCCESS(*status)) {
237     len = ucnv_toUChars(cnv, uchars, ucharsSize, chars,charsSize, status);
238   }
239   return len;
240 }
241 
242 /* Format the date */
243 static void
date(UDate when,const UChar * tz,UDateFormatStyle style,const char * format,UErrorCode * status)244 date(UDate when,
245      const UChar *tz,
246      UDateFormatStyle style,
247      const char *format,
248      UErrorCode *status )
249 {
250   UChar *s = 0;
251   int32_t len = 0;
252   UDateFormat *fmt;
253   UChar uFormat[100];
254 
255   if(U_FAILURE(*status)) return;
256 
257   if( format != NULL ) {
258     if(!strcmp(format,FORMAT_MILLIS)) {
259       printf("%.0f\n", when);
260       return;
261     } else if(!strcmp(format, FORMAT_SECONDS)) {
262       printf("%.3f\n", when/1000.0);
263       return;
264     }
265   }
266 
267   fmt = udat_open(style, style, 0, tz, -1,NULL,0, status);
268   if ( format != NULL ) {
269     charsToUCharsDefault(uFormat,sizeof(uFormat)/sizeof(uFormat[0]),format,-1,status);
270     udat_applyPattern(fmt,FALSE,uFormat,-1);
271   }
272   len = udat_format(fmt, when, 0, len, 0, status);
273   if(*status == U_BUFFER_OVERFLOW_ERROR) {
274     *status = U_ZERO_ERROR;
275     s = (UChar*) malloc(sizeof(UChar) * (len+1));
276     if(s == 0) goto finish;
277     udat_format(fmt, when, s, len + 1, 0, status);
278   }
279   if(U_FAILURE(*status)) goto finish;
280 
281   /* print the date string */
282   uprint(s, stdout, status);
283 
284   /* print a trailing newline */
285   printf("\n");
286 
287  finish:
288   if(U_FAILURE(*status)) {
289     fprintf(stderr, "Error in Print: %s\n", u_errorName(*status));
290   }
291   udat_close(fmt);
292   free(s);
293 }
294 
getWhen(const char * millis,const char * seconds,const char * format,UDateFormatStyle style,const char * parse,const UChar * tz,UErrorCode * status)295 static UDate getWhen(const char *millis, const char *seconds, const char *format,
296                      UDateFormatStyle style, const char *parse, const UChar *tz, UErrorCode *status) {
297   UDateFormat *fmt = NULL;
298   UChar uFormat[100];
299   UChar uParse[256];
300   UDate when=0;
301   int32_t parsepos = 0;
302 
303   if(millis != NULL) {
304     sscanf(millis, "%lf", &when);
305     return when;
306   } else if(seconds != NULL) {
307     sscanf(seconds, "%lf", &when);
308     return when*1000.0;
309   }
310 
311   if(parse!=NULL) {
312     if( format != NULL ) {
313       if(!strcmp(format,FORMAT_MILLIS)) {
314         sscanf(parse, "%lf", &when);
315         return when;
316       } else if(!strcmp(format, FORMAT_SECONDS)) {
317         sscanf(parse, "%lf", &when);
318         return when*1000.0;
319       }
320     }
321 
322     fmt = udat_open(style, style, 0, tz, -1,NULL,0, status);
323     if ( format != NULL ) {
324       charsToUCharsDefault(uFormat,sizeof(uFormat)/sizeof(uFormat[0]), format,-1,status);
325       udat_applyPattern(fmt,FALSE,uFormat,-1);
326     }
327 
328     charsToUCharsDefault(uParse,sizeof(uParse)/sizeof(uParse[0]), parse,-1,status);
329     when = udat_parse(fmt, uParse, -1, &parsepos, status);
330     if(U_FAILURE(*status)) {
331       fprintf(stderr, "Error in Parse: %s\n", u_errorName(*status));
332       if(parsepos > 0 && parsepos <= (int32_t)strlen(parse)) {
333         fprintf(stderr, "ERR>\"%s\" @%d\n"
334                         "ERR> %*s^\n",
335                 parse,parsepos,parsepos,"");
336 
337       }
338     }
339 
340     udat_close(fmt);
341     return when;
342   } else {
343     return ucal_getNow();
344   }
345 }
346 
347 #endif
348