f165bf10e7
The ICU4C sample "date" program just uses the "default" ICU locale. This change lets you pass in an explicit locale argument for testing on platforms like Windows that don't have/use the environment variable "LC_ALL".
357 lines
9.9 KiB
C
357 lines
9.9 KiB
C
/*
|
|
*************************************************************************
|
|
* © 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
|