Using locale settings to detect wheter to use imperial units
In the end I went for the following solution.
public class UnitLocale { public static UnitLocale Imperial = new UnitLocale(); public static UnitLocale Metric = new UnitLocale(); public static UnitLocale getDefault() { return getFrom(Locale.getDefault()); } public static UnitLocale getFrom(Locale locale) { String countryCode = locale.getCountry(); if ("US".equals(countryCode)) return Imperial; // USA if ("LR".equals(countryCode)) return Imperial; // Liberia if ("MM".equals(countryCode)) return Imperial; // Myanmar return Metric; }}
Use it like this for example.
if (UnitLocale.getDefault() == UnitLocale.Imperial) convertToimperial();
If convert methods are also need they can preferably be added to subclasses of UnitLocale. I only needed to detect wheter to use imperial units and send it to the server.
Using int
s over java objects have extremely slim performance gains and makes the code harder to read. Comparing two references in java is comparable in speed to comparing two ints
. Also using objects allow us to add methods to the UnitLocale
class or subclasses such as, convertToMetric, etc.
You could also use an enum instead if you prefer that.
A more or less complete way to do this is this way.
Kotlin:
private fun Locale.toUnitSystem() = when (country.toUpperCase()) { // https://en.wikipedia.org/wiki/United_States_customary_units // https://en.wikipedia.org/wiki/Imperial_units "US" -> UnitSystem.IMPERIAL_US // UK, Myanmar, Liberia, "GB", "MM", "LR" -> UnitSystem.IMPERIAL else -> UnitSystem.METRIC }
Note that there is a difference between UK and US imperial systems, see the wiki articles for more details.
Building on the other nice solutions here, you can also implement this as a Kotlin extension function to the Locale object:
fun Locale.isMetric(): Boolean { return when (country.toUpperCase(this)) { "US", "LR", "MM" -> false else -> true }}
This way, all you need to do is call:
val metric = Locale.getDefault().isMetric()