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