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