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