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