2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.lutron.internal.protocol;
15 import java.math.BigDecimal;
16 import java.math.RoundingMode;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
23 * Holds time durations used by the Lutron protocols
25 * @author Bob Adair - Initial contribution
29 public class LutronDuration {
30 public static final int MAX_SECONDS = 360000 - 1;
31 public static final int MAX_HUNDREDTHS = 99;
33 private static final Pattern PATTERN_SS = Pattern.compile("^(\\d{1,2})$");
34 private static final Pattern PATTERN_SSDEC = Pattern.compile("^(\\d{1,2})\\.(\\d{2})$");
35 private static final Pattern PATTERN_MMSS = Pattern.compile("^(\\d{1,2}):(\\d{2})$");
36 private static final Pattern PATTERN_HHMMSS = Pattern.compile("^(\\d{1,2}):(\\d{2}):(\\d{2})$");
38 public final Integer seconds;
39 public final Integer hundredths;
42 * Constructor accepting duration in seconds
44 public LutronDuration(Integer seconds) {
45 if (seconds < 0 || seconds > MAX_SECONDS) {
46 throw new IllegalArgumentException("Invalid duration");
48 this.seconds = seconds;
53 * Constructor accepting duration in seconds and hundredths of seconds
55 public LutronDuration(Integer seconds, Integer hundredths) {
56 if (seconds < 0 || seconds > MAX_SECONDS || hundredths < 0 || hundredths > MAX_HUNDREDTHS) {
57 throw new IllegalArgumentException("Invalid duration");
59 this.seconds = seconds;
60 this.hundredths = hundredths;
64 * Constructor accepting duration in seconds as a BigDecimal
66 public LutronDuration(BigDecimal seconds) {
67 if (seconds.compareTo(BigDecimal.ZERO) == -1 || seconds.compareTo(new BigDecimal(MAX_SECONDS)) == 1) {
68 new IllegalArgumentException("Invalid duration");
70 this.seconds = seconds.intValue();
71 BigDecimal fractional = seconds.subtract(new BigDecimal(seconds.intValue()));
72 this.hundredths = fractional.movePointRight(2).intValue();
76 * Constructor accepting duration in seconds as a Double
78 public LutronDuration(Double seconds) {
79 this(new BigDecimal(seconds).setScale(2, RoundingMode.HALF_UP));
83 * Constructor accepting duration string of the format: SS.ss, SS, MM:SS, or HH:MM:SS
85 public LutronDuration(String duration) {
86 Matcher matcherSS = PATTERN_SS.matcher(duration);
87 if (matcherSS.find()) {
88 Integer seconds = Integer.valueOf(matcherSS.group(1));
89 this.seconds = seconds;
93 Matcher matcherSSDec = PATTERN_SSDEC.matcher(duration);
94 if (matcherSSDec.find()) {
95 this.seconds = Integer.valueOf(matcherSSDec.group(1));
96 this.hundredths = Integer.valueOf(matcherSSDec.group(2));
99 Matcher matcherMMSS = PATTERN_MMSS.matcher(duration);
100 if (matcherMMSS.find()) {
101 Integer minutes = Integer.valueOf(matcherMMSS.group(1));
102 Integer seconds = Integer.valueOf(matcherMMSS.group(2));
103 this.seconds = minutes * 60 + seconds;
107 Matcher matcherHHMMSS = PATTERN_HHMMSS.matcher(duration);
108 if (matcherHHMMSS.find()) {
109 Integer hours = Integer.valueOf(matcherHHMMSS.group(1));
110 Integer minutes = Integer.valueOf(matcherHHMMSS.group(2));
111 Integer seconds = Integer.valueOf(matcherHHMMSS.group(3));
112 this.seconds = hours * 60 * 60 + minutes * 60 + seconds;
116 throw new IllegalArgumentException("Invalid duration");
119 public String asLipString() {
121 if (hundredths == 0) {
122 return String.valueOf(seconds);
124 return String.format("%d.%02d", seconds, hundredths);
126 } else if (seconds < 3600) {
127 return String.format("%d:%02d", seconds / 60, seconds % 60);
129 return String.format("%d:%02d:%02d", seconds / 3600, (seconds % 3600) / 60, (seconds % 60));
133 public String asLeapString() {
134 Integer seconds = this.seconds;
135 if (seconds.equals(0) && hundredths > 0) {
136 // use 1 second if interval is > 0 and < 1
138 } else if (hundredths >= 50) {
139 // else apply normal rounding of hundredths
142 return String.format("%02d:%02d:%02d", seconds / 3600, (seconds % 3600) / 60, (seconds % 60));
146 public String toString() {
147 return asLipString();