From 4da0eab610b65766b72c55e4369dc79c002af4e0 Mon Sep 17 00:00:00 2001 From: Erdoan Hadzhiyusein <3rdoan@gmail.com> Date: Wed, 13 Sep 2017 15:48:22 +0300 Subject: [PATCH] added time zone in the Paper UI and LocationProvider service Signed-off-by: Erdoan Hadzhiyusein <3rdoan@gmail.com> --- .../i18n/I18nConfigOptionsProvider.java | 56 ++++++++++++++++--- .../ESH-INF/config/i18n.xml | 8 +++ .../smarthome/core/i18n/TimeZoneProvider.java | 25 +++++++++ .../core/internal/i18n/I18nProviderImpl.java | 47 ++++++++++++---- .../discovery/AstroDiscoveryService.java | 1 - 5 files changed, 119 insertions(+), 18 deletions(-) create mode 100644 bundles/core/org.eclipse.smarthome.core/src/main/java/org/eclipse/smarthome/core/i18n/TimeZoneProvider.java diff --git a/bundles/config/org.eclipse.smarthome.config.core/src/main/java/org/eclipse/smarthome/config/core/internal/i18n/I18nConfigOptionsProvider.java b/bundles/config/org.eclipse.smarthome.config.core/src/main/java/org/eclipse/smarthome/config/core/internal/i18n/I18nConfigOptionsProvider.java index 9a063c35df7..7e293ef3c89 100644 --- a/bundles/config/org.eclipse.smarthome.config.core/src/main/java/org/eclipse/smarthome/config/core/internal/i18n/I18nConfigOptionsProvider.java +++ b/bundles/config/org.eclipse.smarthome.config.core/src/main/java/org/eclipse/smarthome/config/core/internal/i18n/I18nConfigOptionsProvider.java @@ -8,10 +8,16 @@ package org.eclipse.smarthome.config.core.internal.i18n; import java.net.URI; +import java.time.ZoneId; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; import java.util.Locale; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; @@ -23,29 +29,65 @@ * {@link ConfigOptionProvider} that provides a list of * * @author Simon Kaufmann - initial contribution and API + * @author Erdoan Hadzhiyusein - Added time zone * */ @Component(immediate = true) public class I18nConfigOptionsProvider implements ConfigOptionProvider { + private static final String NO_OFFSET_FORMAT = "(GMT) %s"; + private static final String NEGATIVE_OFFSET_FORMAT = "%s (GMT%d:%02d)"; + private static final String POSITIVE_OFFSET_FORMAT = "%s (GMT+%d:%02d)"; + @Override public Collection getParameterOptions(URI uri, String param, Locale locale) { if (uri.toString().equals("system:i18n")) { Locale translation = locale != null ? locale : Locale.getDefault(); - if (param.equals("language")) { - return getAvailable(locale, l -> new ParameterOption(l.getLanguage(), l.getDisplayLanguage(translation))); - } else if (param.equals("region")) { - return getAvailable(locale, l -> new ParameterOption(l.getCountry(), l.getDisplayCountry(translation))); - } else if (param.equals("variant")) { - return getAvailable(locale, l -> new ParameterOption(l.getVariant(), l.getDisplayVariant(translation))); + switch (param) { + case "language": + return getAvailable(locale, + l -> new ParameterOption(l.getLanguage(), l.getDisplayLanguage(translation))); + case "region": + return getAvailable(locale, + l -> new ParameterOption(l.getCountry(), l.getDisplayCountry(translation))); + case "variant": + return getAvailable(locale, + l -> new ParameterOption(l.getVariant(), l.getDisplayVariant(translation))); + case "timezone": + Collection collection = new LinkedList(); + Collection ids = ZoneId.getAvailableZoneIds(); + List timeZones = ids.stream().map(TimeZone::getTimeZone) + .collect(Collectors.toList()); + Collections.sort(timeZones, (s1, s2) -> s2.getRawOffset() - s1.getRawOffset()); + // sorting the time zones by offset + for (TimeZone instance : timeZones) { + collection.add(new ParameterOption(instance.getID(), getTimeZoneRepresentation(instance))); + } + return collection; + default: + return null; } } return null; } + private static String getTimeZoneRepresentation(TimeZone tz) { + long hours = TimeUnit.MILLISECONDS.toHours(tz.getRawOffset()); + long minutes = TimeUnit.MILLISECONDS.toMinutes(tz.getRawOffset()) - TimeUnit.HOURS.toMinutes(hours); + minutes = Math.abs(minutes); + final String result; + if (hours > 0) { + result = String.format(POSITIVE_OFFSET_FORMAT, tz.getID(), hours, minutes); + } else if (hours < 0) { + result = String.format(NEGATIVE_OFFSET_FORMAT, tz.getID(), hours, minutes); + } else { + result = String.format(NO_OFFSET_FORMAT, tz.getDisplayName(Locale.getDefault())); + } + return result; + } + private Collection getAvailable(Locale locale, Function mapFunction) { return Arrays.stream(Locale.getAvailableLocales()).map(l -> mapFunction.apply(l)).distinct() .sorted(Comparator.comparing(a -> a.getLabel())).collect(Collectors.toList()); } - } diff --git a/bundles/core/org.eclipse.smarthome.core/ESH-INF/config/i18n.xml b/bundles/core/org.eclipse.smarthome.core/ESH-INF/config/i18n.xml index ec510a49a30..bb092ebae7e 100644 --- a/bundles/core/org.eclipse.smarthome.core/ESH-INF/config/i18n.xml +++ b/bundles/core/org.eclipse.smarthome.core/ESH-INF/config/i18n.xml @@ -43,6 +43,14 @@ true + + + A time zone can be set from the dropdown menu.

+

The underlying system's time zone is the default.

+ ]]> +
+
location diff --git a/bundles/core/org.eclipse.smarthome.core/src/main/java/org/eclipse/smarthome/core/i18n/TimeZoneProvider.java b/bundles/core/org.eclipse.smarthome.core/src/main/java/org/eclipse/smarthome/core/i18n/TimeZoneProvider.java new file mode 100644 index 00000000000..df26b9e90b0 --- /dev/null +++ b/bundles/core/org.eclipse.smarthome.core/src/main/java/org/eclipse/smarthome/core/i18n/TimeZoneProvider.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2014-2017 by the respective copyright holders. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.smarthome.core.i18n; + +import java.util.TimeZone; + +/** + * This interface describes a provider for a location and time zone. + * + * @author Erdoan Hadzhiyusein - Initial contribution and API + */ +public interface TimeZoneProvider { + + /** + * Provides access to the time zone property. + * + * @return the time zone set in the Paper UI and if there isn't one, the default time zone of the underlying system + */ + TimeZone getTimeZone(); +} diff --git a/bundles/core/org.eclipse.smarthome.core/src/main/java/org/eclipse/smarthome/core/internal/i18n/I18nProviderImpl.java b/bundles/core/org.eclipse.smarthome.core/src/main/java/org/eclipse/smarthome/core/internal/i18n/I18nProviderImpl.java index 37553b69ea5..9159b0e471c 100644 --- a/bundles/core/org.eclipse.smarthome.core/src/main/java/org/eclipse/smarthome/core/internal/i18n/I18nProviderImpl.java +++ b/bundles/core/org.eclipse.smarthome.core/src/main/java/org/eclipse/smarthome/core/internal/i18n/I18nProviderImpl.java @@ -11,10 +11,12 @@ import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; +import java.util.TimeZone; import org.apache.commons.lang.StringUtils; import org.eclipse.smarthome.core.i18n.LocaleProvider; import org.eclipse.smarthome.core.i18n.LocationProvider; +import org.eclipse.smarthome.core.i18n.TimeZoneProvider; import org.eclipse.smarthome.core.i18n.TranslationProvider; import org.eclipse.smarthome.core.library.types.PointType; import org.osgi.framework.Bundle; @@ -39,9 +41,10 @@ * @author Thomas Höfer - Added getText operation with arguments * @author Markus Rathgeb - Initial contribution and API of LocaleProvider * @author Stefan Triller - Initial contribution and API of LocationProvider + * @author Erdoan Hadzhiyusein - Added time zone * */ -public class I18nProviderImpl implements TranslationProvider, LocaleProvider, LocationProvider { +public class I18nProviderImpl implements TranslationProvider, LocaleProvider, LocationProvider, TimeZoneProvider { private final Logger logger = LoggerFactory.getLogger(getClass()); @@ -50,6 +53,7 @@ public class I18nProviderImpl implements TranslationProvider, LocaleProvider, Lo private static final String SCRIPT = "script"; private static final String REGION = "region"; private static final String VARIANT = "variant"; + private static final String TIMEZONE = "timezone"; private Locale locale; // TranslationProvider @@ -58,6 +62,7 @@ public class I18nProviderImpl implements TranslationProvider, LocaleProvider, Lo // LocationProvider private static final String LOCATION = "location"; private PointType location; + private TimeZone timeZone; @SuppressWarnings("unchecked") protected void activate(ComponentContext componentContext) { @@ -77,15 +82,10 @@ protected synchronized void modified(Map config) { final String region = (String) config.get(REGION); final String variant = (String) config.get(VARIANT); final String location = (String) config.get(LOCATION); + final String timeZone = (String) config.get(TIMEZONE); - if (location != null) { - try { - this.location = PointType.valueOf(location); - } catch (IllegalArgumentException e) { - // preserve old location or null if none was set before - logger.warn("Could not set new location, keeping old one: ", e.getMessage()); - } - } + setTimeZone(timeZone); + setLocation(location); if (StringUtils.isEmpty(language)) { // at least the language must be defined otherwise the system default locale is used @@ -125,7 +125,29 @@ protected synchronized void modified(Map config) { locale = builder.build(); - logger.info("Locale set to {}, Location set to {}", locale, this.location); + logger.info("Locale set to {}, Location set to {}, Time zone set to {}", locale, this.location, this.timeZone); + } + + private void setLocation(final String location) { + if (location != null) { + try { + this.location = PointType.valueOf(location); + } catch (IllegalArgumentException e) { + // preserve old location or null if none was set before + logger.warn("Could not set new location, keeping old one: ", e); + } + } + } + + private void setTimeZone(final String timeZone) { + if (timeZone != null) { + try { + this.timeZone = TimeZone.getTimeZone(timeZone); + } catch (IllegalArgumentException e) { + this.timeZone = TimeZone.getDefault(); + logger.warn("Could not set a new timezone, the system's default time zone will be used ", e); + } + } } @Override @@ -133,6 +155,11 @@ public PointType getLocation() { return location; } + @Override + public TimeZone getTimeZone() { + return this.timeZone; + } + @Override public Locale getLocale() { if (locale == null) { diff --git a/extensions/binding/org.eclipse.smarthome.binding.astro/src/main/java/org/eclipse/smarthome/binding/astro/discovery/AstroDiscoveryService.java b/extensions/binding/org.eclipse.smarthome.binding.astro/src/main/java/org/eclipse/smarthome/binding/astro/discovery/AstroDiscoveryService.java index 672fffe46c9..5a290b6590a 100644 --- a/extensions/binding/org.eclipse.smarthome.binding.astro/src/main/java/org/eclipse/smarthome/binding/astro/discovery/AstroDiscoveryService.java +++ b/extensions/binding/org.eclipse.smarthome.binding.astro/src/main/java/org/eclipse/smarthome/binding/astro/discovery/AstroDiscoveryService.java @@ -118,5 +118,4 @@ protected void setLocationProvider(LocationProvider locationProvider) { protected void unsetLocationProvider(LocationProvider locationProvider) { this.locationProvider = null; } - }