Browse Source

Improvement to the TbDate.toLocaleString

pull/9220/head
Andrii Shvaika 3 years ago
parent
commit
db48a2d980
  1. 50
      common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DateFormattingOptions.java
  2. 84
      common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbDate.java
  3. 182
      common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbDateTest.java

50
common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/DateFormattingOptions.java

@ -0,0 +1,50 @@
package org.thingsboard.script.api.tbel;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.StringUtils;
import java.time.format.FormatStyle;
import java.util.TimeZone;
@NoArgsConstructor
@Data
class DateFormattingOptions {
private static final TimeZone DEFAULT_TZ = TimeZone.getDefault();
private String timeZone;
private String dateStyle;
private String timeStyle;
@Getter
private String pattern;
public DateFormattingOptions(String timeZone) {
this.timeZone = timeZone;
}
TimeZone getTimeZone() {
return StringUtils.isNotEmpty(timeZone) ? TimeZone.getTimeZone(timeZone) : TimeZone.getDefault();
}
FormatStyle getDateStyle() {
return getFormatStyle(dateStyle, FormatStyle.SHORT);
}
FormatStyle getTimeStyle() {
return getFormatStyle(timeStyle, FormatStyle.MEDIUM);
}
private static FormatStyle getFormatStyle(String style, FormatStyle defaultStyle) {
if (StringUtils.isNotEmpty(style)) {
try {
return FormatStyle.valueOf(style.toUpperCase());
} catch (IllegalArgumentException e) {
return defaultStyle;
}
} else {
return defaultStyle;
}
}
}

84
common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbDate.java

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@ -15,6 +15,9 @@
*/
package org.thingsboard.script.api.tbel;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.StringUtils;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
@ -22,13 +25,16 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import java.util.function.BiFunction;
import java.util.function.Function;
public class TbDate extends Date {
@ -77,15 +83,77 @@ public class TbDate extends Date {
return isoDateFormat.get().format(this);
}
public String toLocaleDateString() {
return toLocaleDateString(null, null);
}
public String toLocaleDateString(String locale) {
return toLocaleDateString(locale, null);
}
public String toLocaleDateString(String localeStr, String optionsStr) {
return toLocaleString(localeStr, optionsStr, (locale, options) -> DateTimeFormatter.ofLocalizedDate(options.getDateStyle()).withLocale(locale));
}
public String toLocaleTimeString() {
return toLocaleTimeString(null, null);
}
public String toLocaleTimeString(String locale) {
return toLocaleTimeString(locale, null);
}
public String toLocaleTimeString(String localeStr, String optionsStr) {
return toLocaleString(localeStr, optionsStr, (locale, options) -> DateTimeFormatter.ofLocalizedTime(options.getTimeStyle()).withLocale(locale));
}
@Override
public String toLocaleString() {
return toLocaleString(null, null);
}
public String toLocaleString(String locale) {
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.forLanguageTag(locale));
return formatter.format(this);
return toLocaleString(locale, null);
}
public String toLocaleString(String locale, String tz) {
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.forLanguageTag(locale));
formatter.setTimeZone(TimeZone.getTimeZone(tz));
return formatter.format(this);
public String toLocaleString(String localeStr, String optionsStr) {
return toLocaleString(localeStr, optionsStr, (locale, options) -> {
String formatPattern =
DateTimeFormatterBuilder.getLocalizedDateTimePattern(
options.getDateStyle(),
options.getTimeStyle(),
IsoChronology.INSTANCE,
locale);
return DateTimeFormatter.ofPattern(formatPattern, locale);
});
}
public String toLocaleString(String localeStr, String optionsStr, BiFunction<Locale, DateFormattingOptions, DateTimeFormatter> formatterBuilder) {
Locale locale = StringUtils.isNotEmpty(localeStr) ? Locale.forLanguageTag(localeStr) : Locale.getDefault();
DateFormattingOptions options = getDateFormattingOptions(optionsStr);
ZonedDateTime zdt = this.toInstant().atZone(options.getTimeZone().toZoneId());
DateTimeFormatter formatter;
if (StringUtils.isNotEmpty(options.getPattern())) {
formatter = new DateTimeFormatterBuilder().appendPattern(options.getPattern()).toFormatter(locale);
} else {
formatter = formatterBuilder.apply(locale, options);
}
return formatter.format(zdt);
}
private static DateFormattingOptions getDateFormattingOptions(String options) {
DateFormattingOptions opt = null;
if (StringUtils.isNotEmpty(options)) {
try {
opt = JacksonUtil.fromString(options, DateFormattingOptions.class);
} catch (IllegalArgumentException iae) {
opt = new DateFormattingOptions(options);
}
}
if (opt == null) {
opt = new DateFormattingOptions();
}
return opt;
}
public static long now() {

182
common/script/script-api/src/test/java/org/thingsboard/script/api/tbel/TbDateTest.java

@ -21,12 +21,24 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.thingsboard.common.util.JacksonUtil;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.FormatStyle;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
@ -124,4 +136,174 @@ class TbDateTest {
.startsWith(datePrefix);
}
@Test
void testToLocaleDateString() {
TbDate d = new TbDate(1693962245000L);
// Depends on time zone, so we just check it works;
Assert.assertNotNull(d.toLocaleDateString());
Assert.assertNotNull(d.toLocaleDateString("en-US"));
Assert.assertEquals("9/5/23", d.toLocaleDateString("en-US", "America/New_York"));
Assert.assertEquals("23. 9. 5.", d.toLocaleDateString("ko-KR", "America/New_York"));
Assert.assertEquals("06.09.23", d.toLocaleDateString( "uk-UA", "Europe/Kiev"));
Assert.assertEquals("5\u200F/9\u200F/2023", d.toLocaleDateString( "ar-EG", "America/New_York"));
Assert.assertEquals("Tuesday, September 5, 2023", d.toLocaleDateString("en-US", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("dateStyle", "full")
.toString()));
Assert.assertEquals("2023년 9월 5일 화요일", d.toLocaleDateString("ko-KR", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("dateStyle", "full")
.toString()));
Assert.assertEquals("середа, 6 вересня 2023 р.", d.toLocaleDateString("uk-UA", JacksonUtil.newObjectNode()
.put("timeZone", "Europe/Kiev")
.put("dateStyle", "full")
.toString()));
Assert.assertEquals("الثلاثاء، 5 سبتمبر 2023", d.toLocaleDateString("ar-EG", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("dateStyle", "full")
.toString()));
Assert.assertEquals("Tuesday 9/5/2023", d.toLocaleDateString("en-US", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("pattern", "EEEE M/d/yyyy")
.toString()));
Assert.assertEquals("화요일 9/5/2023", d.toLocaleDateString("ko-KR", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("pattern", "EEEE M/d/yyyy")
.toString()));
Assert.assertEquals("середа 9/6/2023", d.toLocaleDateString("uk-UA", JacksonUtil.newObjectNode()
.put("timeZone", "Europe/Kiev")
.put("pattern", "EEEE M/d/yyyy")
.toString()));
Assert.assertEquals("الثلاثاء 9/5/2023", d.toLocaleDateString("ar-EG", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("pattern", "EEEE M/d/yyyy")
.toString()));
}
@Test
void testToLocaleTimeString() {
TbDate d = new TbDate(1693962245000L);
// Depends on time zone, so we just check it works;
Assert.assertNotNull(d.toLocaleTimeString());
Assert.assertNotNull(d.toLocaleTimeString("en-US"));
Assert.assertEquals("9:04:05 PM", d.toLocaleTimeString("en-US", "America/New_York"));
Assert.assertEquals("오후 9:04:05", d.toLocaleTimeString("ko-KR", "America/New_York"));
Assert.assertEquals("04:04:05", d.toLocaleTimeString( "uk-UA", "Europe/Kiev"));
Assert.assertEquals("9:04:05 م", d.toLocaleTimeString( "ar-EG", "America/New_York"));
Assert.assertEquals("9:04:05 PM Eastern Daylight Time", d.toLocaleTimeString("en-US", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("timeStyle", "full")
.toString()));
Assert.assertEquals("오후 9시 4분 5초 미 동부 하계 표준시", d.toLocaleTimeString("ko-KR", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("timeStyle", "full")
.toString()));
Assert.assertEquals("04:04:05 за східноєвропейським літнім часом", d.toLocaleTimeString("uk-UA", JacksonUtil.newObjectNode()
.put("timeZone", "Europe/Kiev")
.put("timeStyle", "full")
.toString()));
Assert.assertEquals("9:04:05 م التوقيت الصيفي الشرقي لأمريكا الشمالية", d.toLocaleTimeString("ar-EG", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("timeStyle", "full")
.toString()));
Assert.assertEquals("9:04:05 PM", d.toLocaleTimeString("en-US", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("pattern", "h:mm:ss a")
.toString()));
Assert.assertEquals("9:04:05 오후", d.toLocaleTimeString("ko-KR", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("pattern", "h:mm:ss a")
.toString()));
Assert.assertEquals("4:04:05 дп", d.toLocaleTimeString("uk-UA", JacksonUtil.newObjectNode()
.put("timeZone", "Europe/Kiev")
.put("pattern", "h:mm:ss a")
.toString()));
Assert.assertEquals("9:04:05 م", d.toLocaleTimeString("ar-EG", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("pattern", "h:mm:ss a")
.toString()));
}
@Test
void testToLocaleString() {
TbDate d = new TbDate(1693962245000L);
// Depends on time zone, so we just check it works;
Assert.assertNotNull(d.toLocaleString());
Assert.assertNotNull(d.toLocaleString("en-US"));
Assert.assertEquals("9/5/23, 9:04:05 PM", d.toLocaleString("en-US", "America/New_York"));
Assert.assertEquals("23. 9. 5. 오후 9:04:05", d.toLocaleString("ko-KR", "America/New_York"));
Assert.assertEquals("06.09.23, 04:04:05", d.toLocaleString( "uk-UA", "Europe/Kiev"));
Assert.assertEquals("5\u200F/9\u200F/2023 9:04:05 م", d.toLocaleString( "ar-EG", "America/New_York"));
Assert.assertEquals("Tuesday, September 5, 2023 at 9:04:05 PM Eastern Daylight Time", d.toLocaleString("en-US", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("dateStyle", "full")
.put("timeStyle", "full")
.toString()));
Assert.assertEquals("2023년 9월 5일 화요일 오후 9시 4분 5초 미 동부 하계 표준시", d.toLocaleString("ko-KR", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("dateStyle", "full")
.put("timeStyle", "full")
.toString()));
Assert.assertEquals("середа, 6 вересня 2023 р. о 04:04:05 за східноєвропейським літнім часом", d.toLocaleString("uk-UA", JacksonUtil.newObjectNode()
.put("timeZone", "Europe/Kiev")
.put("dateStyle", "full")
.put("timeStyle", "full")
.toString()));
Assert.assertEquals("الثلاثاء، 5 سبتمبر 2023 9:04:05 م التوقيت الصيفي الشرقي لأمريكا الشمالية", d.toLocaleString("ar-EG", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("dateStyle", "full")
.put("timeStyle", "full")
.toString()));
Assert.assertEquals("9/5/2023, 9:04:05 PM", d.toLocaleString("en-US", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("pattern", "M/d/yyyy, h:mm:ss a")
.toString()));
Assert.assertEquals("9/5/2023, 9:04:05 오후", d.toLocaleString("ko-KR", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("pattern", "M/d/yyyy, h:mm:ss a")
.toString()));
Assert.assertEquals("9/6/2023, 4:04:05 дп", d.toLocaleString("uk-UA", JacksonUtil.newObjectNode()
.put("timeZone", "Europe/Kiev")
.put("pattern", "M/d/yyyy, h:mm:ss a")
.toString()));
Assert.assertEquals("9/5/2023, 9:04:05 م", d.toLocaleString("ar-EG", JacksonUtil.newObjectNode()
.put("timeZone", "America/New_York")
.put("pattern", "M/d/yyyy, h:mm:ss a")
.toString()));
}
private static String toLocalString(TbDate d, Locale locale, ZoneId tz) {
LocalDateTime ldt = d.toInstant().atZone(tz).toLocalDateTime();
// new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale)
String formatPattern =
DateTimeFormatterBuilder.getLocalizedDateTimePattern(
FormatStyle.SHORT,
FormatStyle.MEDIUM,
IsoChronology.INSTANCE,
locale);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern, locale);
return formatter.format(ldt);
}
private static String toLocalString2(TbDate d, Locale locale, ZoneId tz) {
DateFormat dateFormat = SimpleDateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, locale);
dateFormat.setTimeZone(TimeZone.getTimeZone(tz));
return dateFormat.format(d);
}
}

Loading…
Cancel
Save