Skip to content

ICU4J relative date time format #262

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

Merged
merged 19 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package org.unicode.conformance;

import com.google.gson.reflect.TypeToken;
import com.ibm.icu.impl.locale.XCldrStub.ImmutableMap;
import com.ibm.icu.number.NumberFormatter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
Expand All @@ -18,6 +15,7 @@
import org.unicode.conformance.testtype.messageformat2.MessageFormatTester;
import org.unicode.conformance.testtype.numberformatter.NumberFormatterTester;
import org.unicode.conformance.testtype.pluralrules.PluralRulesTester;
import org.unicode.conformance.testtype.relativedatetimeformat.RelativeDateTimeFormatTester;

/**
* Hello world!
Expand Down Expand Up @@ -132,6 +130,8 @@ public static String getTestCaseResponse(String inputLine) throws Exception {
testType = MessageFormatTester.INSTANCE;
} else if (testTypeStr.equals("plural_rules")) {
testType = PluralRulesTester.INSTANCE;
} else if (testTypeStr.equals("rdt_fmt")) {
testType = RelativeDateTimeFormatTester.INSTANCE;
} else {
io.lacuna.bifurcan.IMap<String,Object> response =
parsedInputPersistentMap
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.unicode.conformance.testtype.relativedatetimeformat;

import org.unicode.conformance.testtype.ITestTypeInputJson;

public class RelativeDateTimeFormatInputJson implements ITestTypeInputJson {

public String test_type;

public String label;

public String locale;

public String numberingSystem;

public String count;

public RelativeDateTimeFormatUnits unit;

public RelativeDateTimeFormatStyle style; // E.g., SHORT

public double quantity;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.unicode.conformance.testtype.relativedatetimeformat;

import org.unicode.conformance.testtype.ITestTypeOutputJson;

public class RelativeDateTimeFormatOutputJson implements ITestTypeOutputJson {

public String test_type;

public String label;

public String result;

public String error;

public String error_message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.unicode.conformance.testtype.relativedatetimeformat;

public enum RelativeDateTimeFormatStyle {
LONG,
NARROW,
SHORT;

public static org.unicode.conformance.testtype.relativedatetimeformat.RelativeDateTimeFormatStyle DEFAULT = LONG;

public static org.unicode.conformance.testtype.relativedatetimeformat.RelativeDateTimeFormatStyle getFromString(String s) {
try {
return org.unicode.conformance.testtype.relativedatetimeformat.RelativeDateTimeFormatStyle.valueOf(s.toUpperCase());
} catch (Exception e){
return DEFAULT;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package org.unicode.conformance.testtype.relativedatetimeformat;

import com.ibm.icu.text.DisplayContext;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.text.RelativeDateTimeFormatter;
import com.ibm.icu.text.RelativeDateTimeFormatter.Style;
import com.ibm.icu.util.ULocale;

import io.lacuna.bifurcan.IMap;
import io.lacuna.bifurcan.Map;

import org.unicode.conformance.ExecutorUtils;
import org.unicode.conformance.testtype.ITestType;
import org.unicode.conformance.testtype.ITestTypeInputJson;
import org.unicode.conformance.testtype.ITestTypeOutputJson;

public class RelativeDateTimeFormatTester implements ITestType {

public static RelativeDateTimeFormatTester INSTANCE = new RelativeDateTimeFormatTester();

@Override
public ITestTypeInputJson inputMapToJson(Map<String, Object> inputMapData) {
RelativeDateTimeFormatInputJson result = new RelativeDateTimeFormatInputJson();

result.label = (String) inputMapData.get("label", null);
result.locale = (String) inputMapData.get("locale", null);
result.count = (String) inputMapData.get("count", "0");
result.quantity = Double.parseDouble(result.count);

result.numberingSystem = (String) inputMapData.get("numbering_system", null);

java.util.Map<String,Object> inputOptions =
(java.util.Map<String,Object>) inputMapData.get("options", null);

result.style = RelativeDateTimeFormatStyle.getFromString(
"" + inputOptions.get("style")
);

String unitInput = (String) inputMapData.get("unit", "0");
result.unit = RelativeDateTimeFormatUnits.getFromString(
unitInput);

return result;
}

@Override
public ITestTypeOutputJson execute(ITestTypeInputJson inputJson) {
RelativeDateTimeFormatInputJson input = (RelativeDateTimeFormatInputJson) inputJson;

// partially construct output
RelativeDateTimeFormatOutputJson output = (RelativeDateTimeFormatOutputJson) getDefaultOutputJson();
output.label = input.label;

try {
output.result = getRelativeDateTimeFormatResultString(input);
} catch (Exception e) {
output.error = e.getMessage();
output.error_message = e.getMessage();
return output;
}

// If we get here, it's a pass/fail result (supported options and no runtime errors/exceptions)
return output;
}

@Override
public ITestTypeOutputJson getDefaultOutputJson() {
return new RelativeDateTimeFormatOutputJson();
}

public IMap<String, Object> convertOutputToMap(ITestTypeOutputJson outputJson) {
RelativeDateTimeFormatOutputJson output = (RelativeDateTimeFormatOutputJson) outputJson;
return new io.lacuna.bifurcan.Map<String,Object>()
.put("label", output.label)
.put("result", output.result);
}

public String formatOutputJson(ITestTypeOutputJson outputJson) {
return ExecutorUtils.GSON.toJson(outputJson);
}
public String getRelativeDateTimeFormatResultString(RelativeDateTimeFormatInputJson input) {
ULocale locale = ULocale.forLanguageTag(input.locale);
Style style;
RelativeDateTimeFormatter.RelativeDateTimeUnit unit;

switch (input.unit) {
default:
case DAY: unit = RelativeDateTimeFormatter.RelativeDateTimeUnit.DAY;
break;
case HOUR: unit = RelativeDateTimeFormatter.RelativeDateTimeUnit.HOUR;
break;
case MINUTE: unit = RelativeDateTimeFormatter.RelativeDateTimeUnit.MINUTE;
break;
case MONTH: unit = RelativeDateTimeFormatter.RelativeDateTimeUnit.MONTH;
break;
case QUARTER: unit = RelativeDateTimeFormatter.RelativeDateTimeUnit.QUARTER;
break;
case SECOND: unit = RelativeDateTimeFormatter.RelativeDateTimeUnit.SECOND;
break;
case WEEK: unit = RelativeDateTimeFormatter.RelativeDateTimeUnit.WEEK;
break;
case YEAR: unit = RelativeDateTimeFormatter.RelativeDateTimeUnit.YEAR;
break;
}

switch (input.style) {
case NARROW: style = RelativeDateTimeFormatter.Style.NARROW;
break;
case SHORT: style = RelativeDateTimeFormatter.Style.SHORT;
break;
default:
case LONG: style = RelativeDateTimeFormatter.Style.LONG;
break;
}

NumberFormat nf = null;
DisplayContext dc = DisplayContext.CAPITALIZATION_NONE;

RelativeDateTimeFormatter rdtf =
RelativeDateTimeFormatter.getInstance(locale, nf, style, dc);

return rdtf.format(input.quantity, unit);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.unicode.conformance.testtype.relativedatetimeformat;

public enum RelativeDateTimeFormatUnits {
DAY,
HOUR,
MINUTE,
MONTH,
QUARTER,
SECOND,
WEEK,
YEAR;

public static org.unicode.conformance.testtype.relativedatetimeformat.RelativeDateTimeFormatUnits DEFAULT = DAY;

public static org.unicode.conformance.testtype.relativedatetimeformat.RelativeDateTimeFormatUnits getFromString(String s) {
try {
return org.unicode.conformance.testtype.relativedatetimeformat.RelativeDateTimeFormatUnits.valueOf(s.toUpperCase());
} catch (Exception e){
return DEFAULT;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package org.unicode.conformance.relativedatetimeformat;

import static org.junit.Assert.assertEquals;

import org.junit.Ignore;
import org.junit.Test;
import org.unicode.conformance.testtype.relativedatetimeformat.RelativeDateTimeFormatOutputJson;
import org.unicode.conformance.testtype.relativedatetimeformat.RelativeDateTimeFormatTester;

public class RelativeDateTimeFormatTest {

@Test
public void testEn100SecondsAgo() {
String testInput =
"\t{\"unit\":\"second\",\"count\":\"-100\",\"locale\":\"en-US\",\"options\":{},\"hexhash\":\"ab5dfa48d57aac79202e8e4dfd12b729b8e4a74a\",\"label\":\"0\"}";

RelativeDateTimeFormatOutputJson output =
(RelativeDateTimeFormatOutputJson) RelativeDateTimeFormatTester.INSTANCE.getStructuredOutputFromInputStr(
testInput);

assertEquals("100 seconds ago", output.result);
}

@Test
public void testEnIn100Sec() {
String testInput =
"\t{\"unit\":\"second\",\"count\":\"100\",\"locale\":\"en-US\",\"options\":{\"style\":\"short\"},\"hexhash\":\"ab5dfa48d57aac79202e8e4dfd12b729b8e4a74a\",\"label\":\"0\"}";

RelativeDateTimeFormatOutputJson output =
(RelativeDateTimeFormatOutputJson) RelativeDateTimeFormatTester.INSTANCE.getStructuredOutputFromInputStr(
testInput);

assertEquals("in 100 sec.", output.result);
}

@Test
public void testEnIn100Seconds() {
String testInput =
"\t{\"unit\":\"second\",\"count\":\"100\",\"locale\":\"en-US\",\"options\":{\"style\":\"long\"},\"hexhash\":\"ab5dfa48d57aac79202e8e4dfd12b729b8e4a74a\",\"label\":\"0\"}";

RelativeDateTimeFormatOutputJson output =
(RelativeDateTimeFormatOutputJson) RelativeDateTimeFormatTester.INSTANCE.getStructuredOutputFromInputStr(
testInput);

assertEquals("in 100 seconds", output.result);
}

@Test
public void testEn100SecAgo() {
String testInput =
"\t{\"unit\":\"second\",\"count\":\"-100\",\"locale\":\"en-US\",\"options\":{\"style\":\"short\"},\"hexhash\":\"ab5dfa48d57aac79202e8e4dfd12b729b8e4a74a\",\"label\":\"0\"}";

RelativeDateTimeFormatOutputJson output =
(RelativeDateTimeFormatOutputJson) RelativeDateTimeFormatTester.INSTANCE.getStructuredOutputFromInputStr(
testInput);

assertEquals("100 sec. ago", output.result);
}

@Test
public void testEn100SAgo() {
String testInput =
"\t{\"unit\":\"second\",\"count\":\"-100\",\"locale\":\"en-US\",\"options\":{\"style\":\"narrow\"},\"hexhash\":\"a57aac792\",\"label\":\"0\"}";

RelativeDateTimeFormatOutputJson output =
(RelativeDateTimeFormatOutputJson) RelativeDateTimeFormatTester.INSTANCE.getStructuredOutputFromInputStr(
testInput);

assertEquals("100s ago", output.result);
}

@Ignore
// This doesn't yet handle non-ASCII numbering systems
// https://github.com/unicode-org/conformance/issues/261
@Test
public void testAdlamIn1Year() {
// Adlam string in output
//
String testInput =
"\t{\"unit\":\"second\",\"count\":\"-100\",\"locale\":\"en-US\",\"options\":{\"style\":\"narrow\"},\"numberingSystem\":\"adlm\",\"hexhash\":\"79202e8e\",\"label\":\"0\"}";

RelativeDateTimeFormatOutputJson output =
(RelativeDateTimeFormatOutputJson) RelativeDateTimeFormatTester.INSTANCE.getStructuredOutputFromInputStr(
testInput);

assertEquals("in 𞥑𞥐y", output.result);
}
}
Loading
Loading