/*
*************************************************************************
* © 2016 and later: Unicode, Inc. and others.
* License & terms of use: http://www.unicode.org/copyright.html#License
*************************************************************************
***********************************************************************
* Copyright (C) 1998-2012, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*
* File date.c
*
* Modification History:
*
* Date Name Description
* 06/11/99 stephen Creation.
* 06/16/99 stephen Modified to use uprint.
* 08/11/11 srl added Parse and milli/second in/out
*******************************************************************************
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "unicode/utypes.h"
#include "unicode/ustring.h"
#include "unicode/uclean.h"
#include "unicode/ucnv.h"
#include "unicode/udat.h"
#include "unicode/ucal.h"
#include "uprint.h"
int main(int argc, char **argv);
#if UCONFIG_NO_FORMATTING || UCONFIG_NO_CONVERSION
int main(int argc, char **argv)
{
printf("%s: Sorry, UCONFIG_NO_FORMATTING or UCONFIG_NO_CONVERSION was turned on (see uconfig.h). No formatting can be done. \n", argv[0]);
return 0;
}
#else
/* Protos */
static void usage(void);
static void version(void);
static void date(UDate when, const UChar *tz, UDateFormatStyle style, const char *format, const char *locale, UErrorCode *status);
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);
UConverter *cnv = NULL;
/* The version of date */
#define DATE_VERSION "1.0"
/* "GMT" */
static const UChar GMT_ID [] = { 0x0047, 0x004d, 0x0054, 0x0000 };
#define FORMAT_MILLIS "%"
#define FORMAT_SECONDS "%%"
int
main(int argc,
char **argv)
{
int printUsage = 0;
int printVersion = 0;
int optInd = 1;
char *arg;
const UChar *tz = 0;
UDateFormatStyle style = UDAT_DEFAULT;
UErrorCode status = U_ZERO_ERROR;
const char *format = NULL;
const char *locale = NULL;
char *parse = NULL;
char *seconds = NULL;
char *millis = NULL;
UDate when;
/* parse the options */
for(optInd = 1; optInd < argc; ++optInd) {
arg = argv[optInd];
/* version info */
if(strcmp(arg, "-v") == 0 || strcmp(arg, "--version") == 0) {
printVersion = 1;
}
/* usage info */
else if(strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
printUsage = 1;
}
/* display date in gmt */
else if(strcmp(arg, "-u") == 0 || strcmp(arg, "--gmt") == 0) {
tz = GMT_ID;
}
/* display date in gmt */
else if(strcmp(arg, "-f") == 0 || strcmp(arg, "--full") == 0) {
style = UDAT_FULL;
}
/* display date in long format */
else if(strcmp(arg, "-l") == 0 || strcmp(arg, "--long") == 0) {
style = UDAT_LONG;
}
/* display date in medium format */
else if(strcmp(arg, "-m") == 0 || strcmp(arg, "--medium") == 0) {
style = UDAT_MEDIUM;
}
/* display date in short format */
else if(strcmp(arg, "-s") == 0 || strcmp(arg, "--short") == 0) {
style = UDAT_SHORT;
}
else if(strcmp(arg, "-F") == 0 || strcmp(arg, "--format") == 0) {
if ( optInd + 1 < argc ) {
optInd++;
format = argv[optInd];
}
} else if(strcmp(arg, "-r") == 0) {
if ( optInd + 1 < argc ) {
optInd++;
seconds = argv[optInd];
}
} else if(strcmp(arg, "-R") == 0) {
if ( optInd + 1 < argc ) {
optInd++;
millis = argv[optInd];
}
} else if(strcmp(arg, "-P") == 0) {
if ( optInd + 1 < argc ) {
optInd++;
parse = argv[optInd];
}
}
else if (strcmp(arg, "-L") == 0) {
if (optInd + 1 < argc) {
optInd++;
locale = argv[optInd];
}
}
/* POSIX.1 says all arguments after -- are not options */
else if(strcmp(arg, "--") == 0) {
/* skip the -- */
++optInd;
break;
}
/* unrecognized option */
else if(strncmp(arg, "-", strlen("-")) == 0) {
printf("icudate: invalid option -- %s\n", arg+1);
printUsage = 1;
}
/* done with options, display date */
else {
break;
}
}
/* print usage info */
if(printUsage) {
usage();
return 0;
}
/* print version info */
if(printVersion) {
version();
return 0;
}
/* get the 'when' (or now) */
when = getWhen(millis, seconds, format, locale, style, parse, tz, &status);
if(parse != NULL) {
format = FORMAT_MILLIS; /* output in millis */
}
/* print the date */
date(when, tz, style, format, locale, &status);
ucnv_close(cnv);
u_cleanup();
return (U_FAILURE(status) ? 1 : 0);
}
/* Usage information */
static void
usage()
{
puts("Usage: icudate [OPTIONS]");
puts("Options:");
puts(" -h, --help Print this message and exit.");
puts(" -v, --version Print the version number of date and exit.");
puts(" -u, --gmt Display the date in Greenwich Mean Time.");
puts(" -f, --full Use full display format.");
puts(" -l, --long Use long display format.");
puts(" -m, --medium Use medium display format.");
puts(" -s, --short Use short display format.");
puts(" -F <format>, --format <format> Use <format> as the display format.");
puts(" (Special formats: \"%\" alone is Millis since 1970, \"%%\" alone is Seconds since 1970)");
puts(" -r <seconds> Use <seconds> as the time (Epoch 1970) rather than now.");
puts(" -R <millis> Use <millis> as the time (Epoch 1970) rather than now.");
puts(" -P <string> Parse <string> as the time, output in millis format.");
puts(" -L <string> Use the locale <string> instead of the default ICU locale.");
}
/* Version information */
static void
version()
{
UErrorCode status = U_ZERO_ERROR;
const char *tzVer;
int len = 256;
UChar tzName[256];
printf("icudate version %s, created by Stephen F. Booth.\n",
DATE_VERSION);
puts(U_COPYRIGHT_STRING);
tzVer = ucal_getTZDataVersion(&status);
if(U_FAILURE(status)) {
tzVer = u_errorName(status);
}
printf("\n");
printf("ICU Version: %s\n", U_ICU_VERSION);
printf("ICU Data (major+min): %s\n", U_ICUDATA_NAME);
printf("Default Locale: %s\n", uloc_getDefault());
printf("Time Zone Data Version: %s\n", tzVer);
printf("Default Time Zone: ");
status = U_ZERO_ERROR;
u_init(&status);
len = ucal_getDefaultTimeZone(tzName, len, &status);
if(U_FAILURE(status)) {
fprintf(stderr, " ** Error getting default zone: %s\n", u_errorName(status));
}
uprint(tzName, stdout, &status);
printf("\n\n");
}
static int32_t charsToUCharsDefault(UChar *uchars, int32_t ucharsSize, const char*chars, int32_t charsSize, UErrorCode *status) {
int32_t len=-1;
if(U_FAILURE(*status)) return len;
if(cnv==NULL) {
cnv = ucnv_open(NULL, status);
}
if(cnv&&U_SUCCESS(*status)) {
len = ucnv_toUChars(cnv, uchars, ucharsSize, chars,charsSize, status);
}
return len;
}
/* Format the date */
static void
date(UDate when,
const UChar *tz,
UDateFormatStyle style,
const char *format,
const char *locale,
UErrorCode *status )
{
UChar *s = 0;
int32_t len = 0;
UDateFormat *fmt;
UChar uFormat[100];
if(U_FAILURE(*status)) return;
if( format != NULL ) {
if(!strcmp(format,FORMAT_MILLIS)) {
printf("%.0f\n", when);
return;
} else if(!strcmp(format, FORMAT_SECONDS)) {
printf("%.3f\n", when/1000.0);
return;
}
}
fmt = udat_open(style, style, locale, tz, -1,NULL,0, status);
if ( format != NULL ) {
charsToUCharsDefault(uFormat,sizeof(uFormat)/sizeof(uFormat[0]),format,-1,status);
udat_applyPattern(fmt,FALSE,uFormat,-1);
}
len = udat_format(fmt, when, 0, len, 0, status);
if(*status == U_BUFFER_OVERFLOW_ERROR) {
*status = U_ZERO_ERROR;
s = (UChar*) malloc(sizeof(UChar) * (len+1));
if(s == 0) goto finish;
udat_format(fmt, when, s, len + 1, 0, status);
}
if(U_FAILURE(*status)) goto finish;
/* print the date string */
uprint(s, stdout, status);
/* print a trailing newline */
printf("\n");
finish:
if(U_FAILURE(*status)) {
fprintf(stderr, "Error in Print: %s\n", u_errorName(*status));
}
udat_close(fmt);
free(s);
}
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) {
UDateFormat *fmt = NULL;
UChar uFormat[100];
UChar uParse[256];
UDate when=0;
int32_t parsepos = 0;
if(millis != NULL) {
sscanf(millis, "%lf", &when);
return when;
} else if(seconds != NULL) {
sscanf(seconds, "%lf", &when);
return when*1000.0;
}
if(parse!=NULL) {
if( format != NULL ) {
if(!strcmp(format,FORMAT_MILLIS)) {
sscanf(parse, "%lf", &when);
return when;
} else if(!strcmp(format, FORMAT_SECONDS)) {
sscanf(parse, "%lf", &when);
return when*1000.0;
}
}
fmt = udat_open(style, style, locale, tz, -1,NULL,0, status);
if ( format != NULL ) {
charsToUCharsDefault(uFormat,sizeof(uFormat)/sizeof(uFormat[0]), format,-1,status);
udat_applyPattern(fmt,FALSE,uFormat,-1);
}
charsToUCharsDefault(uParse,sizeof(uParse)/sizeof(uParse[0]), parse,-1,status);
when = udat_parse(fmt, uParse, -1, &parsepos, status);
if(U_FAILURE(*status)) {
fprintf(stderr, "Error in Parse: %s\n", u_errorName(*status));
if(parsepos > 0 && parsepos <= (int32_t)strlen(parse)) {
fprintf(stderr, "ERR>\"%s\" @%d\n"
"ERR> %*s^\n",
parse,parsepos,parsepos,"");
}
}
udat_close(fmt);
return when;
} else {
return ucal_getNow();
}
}
#endif