Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add date/time, list format, relative date/time data. Some executors added in NodeJS and ICU4X. #183

Merged
merged 25 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e027bfa
Starting DateTime format with CPP
sven-oly Feb 9, 2024
b1239a4
Adding date time schema prototypes
sven-oly Feb 10, 2024
40b4478
Start test generator
sven-oly Feb 10, 2024
fca9392
Parsing format.txt
sven-oly Feb 27, 2024
9e9743e
Defer updating date time test data
sven-oly Mar 8, 2024
572d120
Move generator for DateTime to generators
sven-oly Mar 8, 2024
dab45cf
Merge remote-tracking branch 'upstream/main' into startDateTime
sven-oly Mar 8, 2024
d86eaae
Starting DateTime generate parsing
sven-oly Mar 11, 2024
27ab673
Starting DateTime generate parsing
sven-oly Mar 11, 2024
de0c346
Merge remote-tracking branch 'upstream/main' into startDateTime
sven-oly Mar 12, 2024
9d72878
Added NodeJS datetime_fmt
sven-oly Mar 16, 2024
6d7c98b
Generators for datetime and list formatting (from NodeJS)
sven-oly Mar 22, 2024
b4f1016
Starting on CPP for date time and list formatting
sven-oly Mar 22, 2024
b46cb48
Merge remote-tracking branch 'origin' into startDateTime
sven-oly Mar 22, 2024
720741f
Configure node for date time and list formatting
sven-oly Mar 22, 2024
9434024
Add list format generator
sven-oly Mar 22, 2024
2891410
Adding first try with CPP list format
sven-oly Mar 24, 2024
683a078
Update input_string to ISO formatted date/time
sven-oly Mar 25, 2024
d37d074
Add relative date/time format data and Node executor
sven-oly Mar 26, 2024
70c8121
Update to CPP DT format, still not working
sven-oly Mar 26, 2024
f5ec893
DateTime improvements - some passing
sven-oly Mar 30, 2024
7ab23d6
DT test generator to use format_to_parts. DT icu4c with tz and calendar
sven-oly Apr 1, 2024
0392036
More updates to date/time generation
sven-oly Apr 1, 2024
263d9a7
Characterize exponent differences for Number Format verifier
sven-oly Apr 1, 2024
d8dec7c
Update schema details
sven-oly Apr 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion executors/cpp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
TARGET=executor

# All object files (C or C++)
OBJECTS=main.o coll.o langnames.o likely_subtags.o number_fmt.o util.o capi.o
OBJECTS=main.o coll.o datetime_fmt.o langnames.o likely_subtags.o list_fmt.o number_fmt.o util.o capi.o

#### rules
# Load in standard makefile definitions
Expand Down
276 changes: 276 additions & 0 deletions executors/cpp/datetime_fmt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
/********************************************************************
* Comments and license as needed
************************************

/******
* testing datetime format
*/


#include "unicode/utypes.h"
#include "unicode/unistr.h"
#include "unicode/datefmt.h"
#include "unicode/locid.h"
#include "unicode/smpdtfmt.h"
#include "unicode/timezone.h"

#include "unicode/uclean.h"

#include "util.h"
#include <stdio.h>
#include <stdlib.h>

#include <json-c/json.h>

#include <iostream>
#include <string>
#include <cstring>

using icu::Calendar;
using icu::DateFormat;
using icu::SimpleDateFormat;
using icu::TimeZone;

using std::cout;
using std::endl;
using std::string;

icu::DateFormat::EStyle stringToEStyle(string style_string) {
if (style_string == "full") return icu::DateFormat::kFull;
if (style_string == "long") return icu::DateFormat::kLong;
if (style_string == "medium") return icu::DateFormat::kMedium;
if (style_string == "short") return icu::DateFormat::kShort;
return icu::DateFormat::kNone;
}

const string test_datetime_fmt(json_object *json_in) {
UErrorCode status = U_ZERO_ERROR;

json_object *label_obj = json_object_object_get(json_in, "label");
string label_string = json_object_get_string(label_obj);

Calendar *cal = nullptr;
TimeZone *tz = nullptr;

// The locale for formatted output
json_object *locale_label_obj = json_object_object_get(json_in, "locale");
string locale_string;
if (locale_label_obj) {
locale_string = json_object_get_string(locale_label_obj);
} else {
locale_string = "und";
}

Locale displayLocale(locale_string.c_str());
Locale und_locale("und");

// JSON data returned.
json_object *return_json = json_object_new_object();
json_object_object_add(return_json, "label", label_obj);

string calendar_str;

// Get fields out of the options if present
json_object* options_obj = json_object_object_get(json_in, "options");

if (options_obj) {
json_object* cal_item = json_object_object_get(options_obj, "calendar");
if (cal_item) {
calendar_str = json_object_get_string(cal_item);

// Add '@calendar=' + calendar_string to locale
locale_string = locale_string + "@calendar=" + calendar_str;

cout << "# Calendar locale: " << locale_string << endl;
if (tz) {
cal = Calendar::createInstance(*tz, displayLocale, status);
} else {
cal = Calendar::createInstance(displayLocale, status);
}
if (U_FAILURE(status)) {
cout << "# ERROR in createInstance for Calendar" << endl;
json_object_object_add(
return_json,
"error",
json_object_new_string("Error in createInstance for calendar"));
return json_object_to_json_string(return_json);
}
}
}

DateFormat* df;


// Get the input data as a date object.
// Types of input:
// "input_string" parsable ISO formatted string such as
// "2020-03-02 10:15:17 -08:00"

string dateStyle_str;
string timeStyle_str;
string timezone_str;

// Expected values if neither dateStyle nor timeStyle is given explicitly.
icu::DateFormat::EStyle date_style = icu::DateFormat::EStyle::kNone;
icu::DateFormat::EStyle time_style = icu::DateFormat::EStyle::kNone;

if (options_obj) {
json_object* option_item = json_object_object_get(options_obj, "dateStyle");
if (option_item) {
dateStyle_str = json_object_get_string(option_item);
date_style = stringToEStyle(dateStyle_str);
}

option_item = json_object_object_get(options_obj, "timeStyle");
if (option_item) {
timeStyle_str = json_object_get_string(option_item);
time_style = stringToEStyle(timeStyle_str);
}

option_item = json_object_object_get(options_obj, "timeZone");
if (option_item) {
timezone_str = json_object_get_string(option_item);
UnicodeString u_tz(timezone_str.c_str());
tz = TimeZone::createTimeZone(u_tz);
cout << "# Created timezone " << tz << " for " << timezone_str << endl;
}
}

json_object *date_skeleton_obj =
json_object_object_get(json_in, "datetime_skeleton");
if (date_skeleton_obj) {
// Data specifies a date time skeleton. Make a formatter based on this.
string skeleton_string = json_object_get_string(date_skeleton_obj);

UnicodeString u_skeleton(skeleton_string.c_str());
if (cal) {
df = DateFormat::createInstanceForSkeleton(cal,
u_skeleton,
displayLocale,
status);
} else {
df = DateFormat::createInstanceForSkeleton(u_skeleton,
displayLocale,
status);
}
if (U_FAILURE(status)) {
cout << "# ERROR in createInstanceForSkeleton" << endl;
json_object_object_add(
return_json,
"error",
json_object_new_string("Error in createInstanceForSkeleton"));
return json_object_to_json_string(return_json);
}
} else {
// Create default formatter
df = DateFormat::createDateTimeInstance(
date_style,
time_style,
displayLocale);
}

if (df == nullptr) {
cout << "# DATE TIME FORMATTER == nullptr == " << df << endl;
// Post an error in the return
json_object_object_add(
return_json,
"error",
json_object_new_string("Cannot construct datetime formatter"));
return json_object_to_json_string(return_json);
}

if (tz) {
cout <<
"# Setting TZ " <<
tz <<
endl;
df->setTimeZone(*tz);
}


// Use ISO string form of the date/time.
json_object *input_string_obj = json_object_object_get(json_in, "input_string");
// Prefer ISO input as input.
json_object *input_millis = json_object_object_get(json_in, "input_millis");

UDate testDateTime;
if (input_string_obj) {
string input_date_string = json_object_get_string(input_string_obj);

UnicodeString date_ustring(input_date_string.c_str());

SimpleDateFormat iso_date_fmt(u"y-M-d'T'h:m:s.SSSZ", und_locale, status);
if (U_FAILURE(status)) {
string error_name = u_errorName(status);
string error_message =
"# iso_date_fmt constructor failure: " +
error_name;

cout << error_message << endl;

json_object_object_add(
return_json,
"error",
json_object_new_string("No date/time data provided"));

return json_object_to_json_string(return_json);
}

// Get date from the parser if possible.
testDateTime = iso_date_fmt.parse(date_ustring, status);

if (U_FAILURE(status)) {
string error_message = "# iso_date_fmt parse failure: " +
input_date_string + " " +
u_errorName(status);
cout << error_message << endl;

json_object_object_add(
return_json,
"error",
json_object_new_string(error_message.c_str()));

return json_object_to_json_string(return_json);
}
} else
if (input_millis) {
testDateTime = json_object_get_double(input_millis);
} else {
// TODO: Post an error due to missing date/time data.
json_object_object_add(
return_json,
"error",
json_object_new_string("No date/time data provided"));

string return_string = json_object_to_json_string(return_json);
return json_object_to_json_string(return_json);
}

// The output of the formatting
UnicodeString formatted_result;

df->format(testDateTime, formatted_result);

// Get the resulting value as a string
string test_result;
int32_t chars_out; // Results of extracting characters from Unicode string
char test_result_string[1000] = "";
chars_out = formatted_result.extract(test_result_string, 1000, nullptr, status);

if (U_FAILURE(status)) {
// TODO: Return error.
cout << "# formatted result: extract error. " << chars_out << endl;
json_object_object_add(
return_json,
"error",
json_object_new_string("Failed extracting test result"));
return json_object_to_json_string(return_json);
}

// Good calls all around. Send the result!
json_object_object_add(return_json,
"result",
json_object_new_string(test_result_string));

return json_object_to_json_string(return_json);
}
2 changes: 1 addition & 1 deletion executors/cpp/defs.mk
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ CLEANFILES=*~ $(TARGET).out
####################################################################
CC=$(shell icu-config --detect-prefix --cc)
CXX=$(shell icu-config --detect-prefix --cxx)
CPPFLAGS=$(shell icu-config --detect-prefix --cppflags)
CPPFLAGS=$(shell icu-config --detect-prefix --cppflags) -std=c++17
CFLAGS=$(shell icu-config --detect-prefix --cflags)
CXXFLAGS=$(shell icu-config --detect-prefix --cxxflags)
LDFLAGS =$^ $(shell icu-config --detect-prefix --ldflags)
Expand Down
Loading
Loading