]> git.basschouten.com Git - openhab-addons.git/blob
fa916d5d762d3554d69d6fc3a87641908b793405
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.astro.internal.util;
14
15 import java.util.Calendar;
16 import java.util.Date;
17 import java.util.regex.Pattern;
18
19 import org.apache.commons.lang.time.DateUtils;
20 import org.openhab.binding.astro.internal.config.AstroChannelConfig;
21 import org.openhab.binding.astro.internal.model.Range;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 /**
26  * Common used DateTime functions.
27  *
28  * @author Gerhard Riegler - Initial contribution
29  */
30 public class DateTimeUtils {
31     private static final Logger LOGGER = LoggerFactory.getLogger(DateTimeUtils.class);
32     private static final Pattern HHMM_PATTERN = Pattern.compile("^([0-1][0-9]|2[0-3])(:[0-5][0-9])$");
33
34     public static final double J1970 = 2440588.0;
35     public static final double MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
36
37     /** Constructor */
38     private DateTimeUtils() {
39         throw new IllegalAccessError("Non-instantiable");
40     }
41
42     /**
43      * Truncates the time from the calendar object.
44      */
45     public static Calendar truncateToMidnight(Calendar calendar) {
46         return DateUtils.truncate(calendar, Calendar.DAY_OF_MONTH);
47     }
48
49     /**
50      * Creates a Range object within the specified months and days. The start
51      * time is midnight, the end time is end of the day.
52      */
53     public static Range getRange(int startYear, int startMonth, int startDay, int endYear, int endMonth, int endDay) {
54         Calendar start = Calendar.getInstance();
55         start.set(Calendar.YEAR, startYear);
56         start.set(Calendar.MONTH, startMonth);
57         start.set(Calendar.DAY_OF_MONTH, startDay);
58         start = truncateToMidnight(start);
59
60         Calendar end = Calendar.getInstance();
61         end.set(Calendar.YEAR, endYear);
62         end.set(Calendar.MONTH, endMonth);
63         end.set(Calendar.DAY_OF_MONTH, endDay);
64         end.set(Calendar.HOUR_OF_DAY, 23);
65         end.set(Calendar.MINUTE, 59);
66         end.set(Calendar.SECOND, 59);
67         end.set(Calendar.MILLISECOND, 999);
68
69         return new Range(start, end);
70     }
71
72     /**
73      * Returns a calendar object from a julian date.
74      */
75     public static Calendar toCalendar(double julianDate) {
76         if (Double.compare(julianDate, Double.NaN) == 0 || julianDate == 0) {
77             return null;
78         }
79         long millis = (long) ((julianDate + 0.5 - J1970) * MILLISECONDS_PER_DAY);
80         Calendar cal = Calendar.getInstance();
81         cal.setTimeInMillis(millis);
82         return DateUtils.round(cal, Calendar.MINUTE);
83     }
84
85     /**
86      * Returns the julian date from the calendar object.
87      */
88     public static double dateToJulianDate(Calendar calendar) {
89         return calendar.getTimeInMillis() / MILLISECONDS_PER_DAY - 0.5 + J1970;
90     }
91
92     /**
93      * Returns the midnight julian date from the calendar object.
94      */
95     public static double midnightDateToJulianDate(Calendar calendar) {
96         return dateToJulianDate(truncateToMidnight(calendar));
97     }
98
99     /**
100      * Returns the end of day from the calendar object.
101      */
102     public static Calendar endOfDayDate(Calendar calendar) {
103         Calendar cal = (Calendar) calendar.clone();
104         cal = DateUtils.ceiling(cal, Calendar.DATE);
105         cal.add(Calendar.MILLISECOND, -1);
106         return cal;
107     }
108
109     /**
110      * Returns the end of day julian date from the calendar object.
111      */
112     public static double endOfDayDateToJulianDate(Calendar calendar) {
113         return dateToJulianDate(endOfDayDate(calendar));
114     }
115
116     /**
117      * Returns the year of the calendar object as a decimal value.
118      */
119     public static double getDecimalYear(Calendar calendar) {
120         return calendar.get(Calendar.YEAR)
121                 + (double) calendar.get(Calendar.DAY_OF_YEAR) / calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
122     }
123
124     /**
125      * Converts the time (hour.minute) to a calendar object.
126      */
127     public static Calendar timeToCalendar(Calendar calendar, double time) {
128         if (time < 0.0) {
129             return null;
130         }
131         Calendar cal = (Calendar) calendar.clone();
132         int hour = 0;
133         int minute = 0;
134         if (time == 24.0) {
135             cal.add(Calendar.DAY_OF_MONTH, 1);
136         } else {
137             hour = (int) time;
138             minute = (int) ((time * 100) - (hour * 100));
139         }
140         cal.set(Calendar.HOUR_OF_DAY, hour);
141         cal.set(Calendar.MINUTE, minute);
142         return DateUtils.truncate(cal, Calendar.MINUTE);
143     }
144
145     /**
146      * Returns true, if two calendar objects are on the same day ignoring time.
147      */
148     public static boolean isSameDay(Calendar cal1, Calendar cal2) {
149         return cal1 != null && cal2 != null && DateUtils.isSameDay(cal1, cal2);
150     }
151
152     /**
153      * Returns a date object from a calendar.
154      */
155     public static Date getDate(Calendar calendar) {
156         return calendar == null ? null : calendar.getTime();
157     }
158
159     /**
160      * Returns the next Calendar from today.
161      */
162     public static Calendar getNextFromToday(Calendar... calendars) {
163         return getNext(Calendar.getInstance(), calendars);
164     }
165
166     static Calendar getNext(Calendar now, Calendar... calendars) {
167         Calendar next = null;
168         Calendar firstSeasonOfYear = null;
169         for (Calendar calendar : calendars) {
170             if (firstSeasonOfYear == null || calendar.before(firstSeasonOfYear)) {
171                 firstSeasonOfYear = calendar;
172             }
173             if (calendar.after(now) && (next == null || calendar.before(next))) {
174                 next = calendar;
175             }
176         }
177         return next == null ? firstSeasonOfYear : next;
178     }
179
180     /**
181      * Returns true, if cal1 is greater or equal than cal2, ignoring seconds.
182      */
183     public static boolean isTimeGreaterEquals(Calendar cal1, Calendar cal2) {
184         Calendar truncCal1 = DateUtils.truncate(cal1, Calendar.MINUTE);
185         Calendar truncCal2 = DateUtils.truncate(cal2, Calendar.MINUTE);
186         return truncCal1.getTimeInMillis() >= truncCal2.getTimeInMillis();
187     }
188
189     /**
190      * Applies the config to the given calendar.
191      */
192     public static Calendar applyConfig(Calendar cal, AstroChannelConfig config) {
193         Calendar cCal = cal;
194         if (config.offset != 0) {
195             Calendar cOffset = Calendar.getInstance();
196             cOffset.setTime(cCal.getTime());
197             cOffset.add(Calendar.MINUTE, config.offset);
198             cCal = cOffset;
199         }
200
201         Calendar cEarliest = adjustTime(cCal, getMinutesFromTime(config.earliest));
202         if (cCal.before(cEarliest)) {
203             return cEarliest;
204         }
205         Calendar cLatest = adjustTime(cCal, getMinutesFromTime(config.latest));
206         if (cCal.after(cLatest)) {
207             return cLatest;
208         }
209
210         return cCal;
211     }
212
213     private static Calendar adjustTime(Calendar cal, int minutes) {
214         if (minutes > 0) {
215             Calendar cTime = Calendar.getInstance();
216             cTime = DateUtils.truncate(cal, Calendar.DAY_OF_MONTH);
217             cTime.add(Calendar.MINUTE, minutes);
218             return cTime;
219         }
220         return cal;
221     }
222
223     /**
224      * Parses a HH:MM string and returns the minutes.
225      */
226     private static int getMinutesFromTime(String configTime) {
227         if (configTime != null) {
228             String time = configTime.trim();
229             if (!time.isEmpty()) {
230                 try {
231                     if (!HHMM_PATTERN.matcher(time).matches()) {
232                         throw new NumberFormatException();
233                     } else {
234                         String[] elements = time.split(":");
235                         int hour = Integer.parseInt(elements[0]);
236                         int minutes = Integer.parseInt(elements[1]);
237                         return (hour * 60) + minutes;
238                     }
239                 } catch (NumberFormatException ex) {
240                     LOGGER.warn(
241                             "Can not parse astro channel configuration '{}' to hour and minutes, use pattern hh:mm, ignoring!",
242                             time);
243                 }
244
245             }
246         }
247         return 0;
248     }
249 }