• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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, 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
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   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
usage()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
version()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 
charsToUCharsDefault(UChar * uchars,int32_t ucharsSize,const char * chars,int32_t charsSize,UErrorCode * status)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
date(UDate when,const UChar * tz,UDateFormatStyle style,const char * format,const char * locale,UErrorCode * status)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 
getWhen(const char * millis,const char * seconds,const char * format,const char * locale,UDateFormatStyle style,const char * parse,const UChar * tz,UErrorCode * status)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