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.util; 015 016import static java.lang.Math.max; 017import static java.lang.Math.toRadians; 018 019import java.time.Instant; 020import java.time.LocalDate; 021import java.time.LocalDateTime; 022import java.time.LocalTime; 023import java.time.ZoneId; 024import java.time.ZonedDateTime; 025import java.time.temporal.ChronoUnit; 026import java.util.Objects; 027 028import org.shredzone.commons.suncalc.param.GenericParameter; 029import org.shredzone.commons.suncalc.param.LocationParameter; 030import org.shredzone.commons.suncalc.param.TimeParameter; 031 032/** 033 * A base implementation of {@link LocationParameter} and {@link TimeParameter}. 034 * <p> 035 * For internal use only. 036 * 037 * @param <T> 038 * Type of the final builder 039 */ 040@SuppressWarnings("unchecked") 041public class BaseBuilder<T> implements GenericParameter<T>, LocationParameter<T>, 042 TimeParameter<T>, Cloneable { 043 044 private double lat = 0.0; 045 private double lng = 0.0; 046 private double height = 0.0; 047 private ZonedDateTime dateTime = ZonedDateTime.now(); 048 049 @Override 050 public T on(ZonedDateTime dateTime) { 051 this.dateTime = Objects.requireNonNull(dateTime, "dateTime"); 052 return (T) this; 053 } 054 055 @Override 056 public T on(LocalDateTime dateTime) { 057 Objects.requireNonNull(dateTime, "dateTime"); 058 return on(ZonedDateTime.of(dateTime, this.dateTime.getZone())); 059 } 060 061 @Override 062 public T on(LocalDate date) { 063 Objects.requireNonNull(date, "date"); 064 return on(ZonedDateTime.of(date, LocalTime.MIDNIGHT, dateTime.getZone())); 065 } 066 067 @Override 068 public T on(Instant instant) { 069 Objects.requireNonNull(instant, "instant"); 070 return on(ZonedDateTime.ofInstant(instant, dateTime.getZone())); 071 } 072 073 @Override 074 public T on(int year, int month, int date, int hour, int minute, int second) { 075 return on(ZonedDateTime.of(year, month, date, hour, minute, second, 0, dateTime.getZone())); 076 } 077 078 @Override 079 public T now() { 080 return on(ZonedDateTime.now(dateTime.getZone())); 081 } 082 083 @Override 084 public T plusDays(int days) { 085 return on(dateTime.plusDays(days)); 086 } 087 088 @Override 089 public T midnight() { 090 return on(dateTime.truncatedTo(ChronoUnit.DAYS)); 091 } 092 093 @Override 094 public T timezone(ZoneId tz) { 095 Objects.requireNonNull(tz, "tz"); 096 on(dateTime.withZoneSameLocal(tz)); 097 return (T) this; 098 } 099 100 @Override 101 public T latitude(double lat) { 102 if (lat < -90.0 || lat > 90.0) { 103 throw new IllegalArgumentException("Latitude out of range, -90.0 <= " + lat + " <= 90.0"); 104 } 105 this.lat = lat; 106 return (T) this; 107 } 108 109 @Override 110 public T longitude(double lng) { 111 if (lng < -180.0 || lng > 180.0) { 112 throw new IllegalArgumentException("Longitude out of range, -180.0 <= " + lng + " <= 180.0"); 113 } 114 this.lng = lng; 115 return (T) this; 116 } 117 118 @Override 119 public T height(double h) { 120 this.height = max(h, 0.0); 121 return (T) this; 122 } 123 124 @Override 125 public T sameTimeAs(TimeParameter<?> t) { 126 if (! (t instanceof BaseBuilder)) { 127 throw new IllegalArgumentException("Cannot read the TimeParameter"); 128 } 129 this.dateTime = ((BaseBuilder<?>) t).dateTime; 130 return (T) this; 131 } 132 133 @Override 134 public T sameLocationAs(LocationParameter<?> l) { 135 if (! (l instanceof BaseBuilder)) { 136 throw new IllegalArgumentException("Cannot read the LocationParameter"); 137 } 138 BaseBuilder<?> origin = (BaseBuilder<?>) l; 139 this.lat = origin.lat; 140 this.lng = origin.lng; 141 this.height = origin.height; 142 return (T) this; 143 } 144 145 @Override 146 public T copy() { 147 try { 148 return (T) clone(); 149 } catch (CloneNotSupportedException ex) { 150 throw new RuntimeException(ex); // Should never be thrown anyway 151 } 152 } 153 154 /** 155 * Returns the longitude. 156 * 157 * @return Longitude, in degrees. 158 */ 159 public double getLongitude() { 160 return lng; 161 } 162 163 /** 164 * Returns the latitude. 165 * 166 * @return Latitude, in degrees. 167 */ 168 public double getLatitude() { 169 return lat; 170 } 171 172 /** 173 * Returns the longitude. 174 * 175 * @return Longitude, in radians. 176 */ 177 public double getLongitudeRad() { 178 return toRadians(lng); 179 } 180 181 /** 182 * Returns the latitude. 183 * 184 * @return Latitude, in radians. 185 */ 186 public double getLatitudeRad() { 187 return toRadians(lat); 188 } 189 190 /** 191 * Returns the height, in meters above sea level. 192 * 193 * @return Height, meters above sea level 194 */ 195 public double getHeight() { 196 return height; 197 } 198 199 /** 200 * Returns the {@link JulianDate} to be used. 201 * 202 * @return {@link JulianDate} 203 */ 204 public JulianDate getJulianDate() { 205 return new JulianDate(dateTime); 206 } 207 208}