001/*
002 * Shredzone Commons - suncalc
003 *
004 * Copyright (C) 2017 Richard "Shred" K├Ârber
005 *   http://commons.shredzone.org
006 *
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
013 */
014package org.shredzone.commons.suncalc.param;
015
016import java.time.Instant;
017import java.time.LocalDate;
018import java.time.LocalDateTime;
019import java.time.ZoneId;
020import java.time.ZonedDateTime;
021import java.util.Calendar;
022import java.util.Date;
023import java.util.Objects;
024import java.util.TimeZone;
025
026/**
027 * Time based parameters.
028 * <p>
029 * Use them to give information about the desired time. If ommitted, the current time and
030 * the system's time zone is used.
031 *
032 * @param <T>
033 *            Type of the final builder
034 */
035@SuppressWarnings("unchecked")
036public interface TimeParameter<T> {
037
038    /**
039     * Sets date and time. Note that also seconds can be passed in for convenience, but
040     * the results are not that accurate.
041     *
042     * @param year
043     *            Year
044     * @param month
045     *            Month (1 = January, 2 = February, ...)
046     * @param date
047     *            Day of month
048     * @param hour
049     *            Hour of day
050     * @param minute
051     *            Minute
052     * @param second
053     *            Second
054     * @return itself
055     */
056    T on(int year, int month, int date, int hour, int minute, int second);
057
058    /**
059     * Sets midnight of the year, month and date.
060     *
061     * @param year
062     *            Year
063     * @param month
064     *            Month (1 = January, 2 = February, ...)
065     * @param date
066     *            Day of month
067     * @return itself
068     */
069    default T on(int year, int month, int date) {
070        return on(year, month, date, 0, 0, 0);
071    }
072
073    /**
074     * Uses the given {@link ZonedDateTime} instance.
075     *
076     * @param dateTime
077     *            {@link ZonedDateTime} to be used.
078     * @return itself
079     */
080    T on(ZonedDateTime dateTime);
081
082    /**
083     * Uses the given {@link LocalDateTime} instance.
084     *
085     * @param dateTime
086     *         {@link LocalDateTime} to be used.
087     * @return itself
088     */
089    T on(LocalDateTime dateTime);
090
091    /**
092     * Uses the given {@link LocalDate} instance, and assumes midnight.
093     *
094     * @param date
095     *         {@link LocalDate} to be used.
096     * @return itself
097     */
098    T on(LocalDate date);
099
100    /**
101     * Uses the given {@link Instant} instance.
102     *
103     * @param instant
104     *            {@link Instant} to be used.
105     * @return itself
106     */
107    T on(Instant instant);
108
109    /**
110     * Uses the given {@link Date} instance.
111     *
112     * @param date
113     *         {@link Date} to be used.
114     * @return itself
115     */
116    default T on(Date date) {
117        Objects.requireNonNull(date, "date");
118        return on(date.toInstant());
119    }
120
121    /**
122     * Uses the given {@link Calendar} instance.
123     *
124     * @param cal
125     *         {@link Calendar} to be used
126     * @return itself
127     */
128    default T on(Calendar cal) {
129        Objects.requireNonNull(cal, "cal");
130        return on(ZonedDateTime.ofInstant(cal.toInstant(), cal.getTimeZone().toZoneId()));
131    }
132
133    /**
134     * Sets the current date and time. This is the default.
135     *
136     * @return itself
137     */
138    T now();
139
140    /**
141     * Sets the time to the start of the current date ("last midnight").
142     *
143     * @return itself
144     */
145    T midnight();
146
147    /**
148     * Adds a number of days to the current date.
149     *
150     * @param days
151     *            Number of days to add
152     * @return itself
153     */
154    T plusDays(int days);
155
156    /**
157     * Sets today, midnight.
158     * <p>
159     * It is the same as <code>now().midnight()</code>.
160     *
161     * @return itself
162     */
163    default T today() {
164        now();
165        midnight();
166        return (T) this;
167    }
168
169    /**
170     * Sets tomorrow, midnight.
171     * <p>
172     * It is the same as <code>now().midnight().plusDays(1)</code>.
173     *
174     * @return itself
175     */
176    default T tomorrow() {
177        today();
178        plusDays(1);
179        return (T) this;
180    }
181
182    /**
183     * Sets the given {@link ZoneId}. The local time is retained, so the parameter order
184     * is not important.
185     *
186     * @param tz
187     *            {@link ZoneId} to be used.
188     * @return itself
189     */
190    T timezone(ZoneId tz);
191
192    /**
193     * Sets the given timezone. This is a convenience method that just invokes
194     * {@link ZoneId#of(String)}.
195     *
196     * @param id
197     *            ID of the time zone.
198     * @return itself
199     * @see ZoneId#of(String)
200     */
201    default T timezone(String id) {
202        return timezone(ZoneId.of(id));
203    }
204
205    /**
206     * Sets the system's timezone. This is the default.
207     *
208     * @return itself
209     */
210    default T localTime() {
211        return timezone(ZoneId.systemDefault());
212    }
213
214    /**
215     * Sets the time zone to UTC.
216     *
217     * @return itself
218     */
219    default T utc() {
220        return timezone("UTC");
221    }
222
223    /**
224     * Sets the {@link TimeZone}.
225     *
226     * @param tz {@link TimeZone} to be used
227     * @return itself
228     */
229    default T timezone(TimeZone tz) {
230        Objects.requireNonNull(tz, "tz");
231        return timezone(tz.toZoneId());
232    }
233
234    /**
235     * Uses the same time as given in the {@link TimeParameter}.
236     * <p>
237     * Changes to the source parameter will not affect this parameter, though.
238     *
239     * @param t  {@link TimeParameter} to be used.
240     * @return itself
241     */
242    T sameTimeAs(TimeParameter<?> t);
243
244}