diff options
| author | Aaron <51387595+AzureAaron@users.noreply.github.com> | 2025-02-14 21:12:32 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-15 10:12:32 +0800 |
| commit | 285085d01f1fa5ffe55d88975f6155a486118aed (patch) | |
| tree | 861e74f11277fa15d85e756ff6fd0749cbeeded2 /src | |
| parent | 2270b4925aa1f7c4e64371c85e8354bb2f3fdb55 (diff) | |
| download | Skyblocker-285085d01f1fa5ffe55d88975f6155a486118aed.tar.gz Skyblocker-285085d01f1fa5ffe55d88975f6155a486118aed.tar.bz2 Skyblocker-285085d01f1fa5ffe55d88975f6155a486118aed.zip | |
Formatters (#1151)
* Formatters
* java yap
---------
Co-authored-by: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/java/de/hysky/skyblocker/utils/Formatters.java | 88 | ||||
| -rw-r--r-- | src/test/java/de/hysky/skyblocker/utils/FormattersTest.java | 61 |
2 files changed, 149 insertions, 0 deletions
diff --git a/src/main/java/de/hysky/skyblocker/utils/Formatters.java b/src/main/java/de/hysky/skyblocker/utils/Formatters.java new file mode 100644 index 00000000..539f9d67 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/Formatters.java @@ -0,0 +1,88 @@ +package de.hysky.skyblocker.utils; + +import java.text.NumberFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +import com.ibm.icu.text.DateTimePatternGenerator; + +import ca.weblite.objc.Client; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.Util; + +/** + * Provides useful constants for formatting numbers and dates. If you need to make slight tweaks to a formatter + * then {@link NumberFormat#clone()} the object and modify it as needed. + */ +public class Formatters { + /** + * Formats numbers as integers with commas. + * + * Example: 100,000,000 + */ + public static final NumberFormat INTEGER_NUMBERS = NumberFormat.getIntegerInstance(Locale.US); + /** + * Formats numbers as floats with up to two digits of precision. + * + * Example: 100,000.15 + */ + public static final NumberFormat DOUBLE_NUMBERS = Util.make(NumberFormat.getInstance(Locale.US), nf -> nf.setMaximumFractionDigits(2)); + /** + * Formats numbers as floats with up to one digit of precision. + * + * Example: 100,000.1 + */ + public static final NumberFormat FLOAT_NUMBERS = Util.make(NumberFormat.getInstance(Locale.US), nf -> nf.setMaximumFractionDigits(1)); + /** + * Formats integer numbers in a short format. + * + * Examples: 10B, 1M, and 5K. + */ + public static final NumberFormat SHORT_INTEGER_NUMBERS = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT); + /** + * Formats float numbers in a short format. + * + * Examples: 17.3B, 1.5M, and 10.8K. + */ + public static final NumberFormat SHORT_FLOAT_NUMBERS = Util.make(NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT), nf -> nf.setMinimumFractionDigits(1)); + /** + * Formats dates to a standard format. + * + * Examples: Thu Jan 30 2025 2:00:10 PM, Thu Jan 30 2025 14:00:10 + */ + public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("E MMM d yyyy " + getTimeFormat(), Locale.US).withZone(ZoneId.systemDefault()); + + /** + * Returns the formatting for the time, always returns 12 hour in development environments for testing purposes. + */ + private static String getTimeFormat() { + return is12HourClock() || FabricLoader.getInstance().isDevelopmentEnvironment() ? "h:mm:ss a" : "HH:mm:ss"; + } + + /** + * Determines whether to use the 12 or 24 hour clock for formatting time.<br><br> + * + * On macOS this reads the preference for the system clock's time format which accounts for whether a user + * chooses 12 or 24 hour time in the System Settings.<br><br> + * + * On other platforms, the time format follows the default for the user's current locale. + * + * @see <a href="https://developer.apple.com/documentation/foundation/nsdateformatter/1408112-dateformatfromtemplate?language=objc">NSDateFormatter</a> + * @see <a href="https://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Field_Symbol_Table">Unicode Locale Data Markup Language (LDML)</a> + */ + private static boolean is12HourClock() { + //The j formatting template returns the preferred formatting for the time + //If the format contains a (am/pm pattern) then the preference is to use the 12 hour clock, otherwise its the 24 hour clock + if (MinecraftClient.IS_SYSTEM_MAC) { + Object locale = Client.getInstance().send("NSLocale", "currentLocale"); + String timeFormat = (String) Client.getInstance().send("NSDateFormatter", "dateFormatFromTemplate:options:locale:", "j", 0, locale); + + return timeFormat.contains("a"); + } else { + return DateTimePatternGenerator.getInstance(Locale.getDefault()).getBestPattern("j").contains("a"); + } + } +} + diff --git a/src/test/java/de/hysky/skyblocker/utils/FormattersTest.java b/src/test/java/de/hysky/skyblocker/utils/FormattersTest.java new file mode 100644 index 00000000..a564eb06 --- /dev/null +++ b/src/test/java/de/hysky/skyblocker/utils/FormattersTest.java @@ -0,0 +1,61 @@ +package de.hysky.skyblocker.utils; + +import java.time.Instant; +import java.util.TimeZone; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public class FormattersTest { + + @BeforeAll + public static void setupEnvironment() { + TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + } + + @Test + void testIntegerNumbers() { + Assertions.assertEquals("100,000,000", Formatters.INTEGER_NUMBERS.format(100_000_000)); + Assertions.assertEquals("99,999,999", Formatters.INTEGER_NUMBERS.format(99_999_999.4)); + Assertions.assertEquals("88,888,888", Formatters.INTEGER_NUMBERS.format(88_888_888.5)); //Half even rounding + Assertions.assertEquals("77,777,777", Formatters.INTEGER_NUMBERS.format(77_777_776.7)); + } + + @Test + void testDoubleNumbers() { + Assertions.assertEquals("100,000,000.15", Formatters.DOUBLE_NUMBERS.format(100_000_000.152341)); + Assertions.assertEquals("99,999,999.98", Formatters.DOUBLE_NUMBERS.format(99_999_999.978)); + } + + @Test + void testFloatNumbers() { + Assertions.assertEquals("100,000,000.8", Formatters.FLOAT_NUMBERS.format(100_000_000.7834)); + Assertions.assertEquals("99,999,999.8", Formatters.FLOAT_NUMBERS.format(99_999_999.84243)); + } + + @Test + void testShortIntegerNumbers() { + Assertions.assertEquals("16B", Formatters.SHORT_INTEGER_NUMBERS.format(15_500_000_000L)); + Assertions.assertEquals("10M", Formatters.SHORT_INTEGER_NUMBERS.format(10_200_000)); + Assertions.assertEquals("5K", Formatters.SHORT_INTEGER_NUMBERS.format(5_000)); + } + + @Test + void testShortFloatNumbers() { + Assertions.assertEquals("14.5B", Formatters.SHORT_FLOAT_NUMBERS.format(14_500_000_000L)); + Assertions.assertEquals("8.3M", Formatters.SHORT_FLOAT_NUMBERS.format(8_300_000)); + Assertions.assertEquals("24.7K", Formatters.SHORT_FLOAT_NUMBERS.format(24_740)); + } + + @Test + void testDates() { + long Thu_Jan_30th_2025_at_4_10_00_PM = 1738253400000L; + long Fri_Jan_31st_2025_at_11_11_00_AM = 1738321860000L; + long Sat_Feb_1st_2025_at_12_00_01_AM = 1738368001000L; + + Assertions.assertEquals("Thu Jan 30 2025 4:10:00 PM", Formatters.DATE_FORMATTER.format(Instant.ofEpochMilli(Thu_Jan_30th_2025_at_4_10_00_PM))); + Assertions.assertEquals("Fri Jan 31 2025 11:11:00 AM", Formatters.DATE_FORMATTER.format(Instant.ofEpochMilli(Fri_Jan_31st_2025_at_11_11_00_AM))); + Assertions.assertEquals("Sat Feb 1 2025 12:00:01 AM", Formatters.DATE_FORMATTER.format(Instant.ofEpochMilli(Sat_Feb_1st_2025_at_12_00_01_AM))); + } +} |
