| 200 | * @throws IllegalArgumentException if range check fails |
| 201 | */ |
| 202 | public static ZonalOffset atLongitude(BigDecimal longitude) { |
| 203 | |
| 204 | if ( |
| 205 | (longitude.compareTo(DECIMAL_POS_180) > 0) |
| 206 | || (longitude.compareTo(DECIMAL_NEG_180) < 0) |
| 207 | ) { |
| 208 | throw new IllegalArgumentException("Out of range: " + longitude); |
| 209 | } |
| 210 | |
| 211 | BigDecimal offset = longitude.multiply(DECIMAL_240); |
| 212 | BigDecimal integral = offset.setScale(0, RoundingMode.DOWN); |
| 213 | BigDecimal delta = offset.subtract(integral); |
| 214 | BigDecimal decimal = delta.setScale(9, RoundingMode.HALF_UP).multiply(MRD); |
| 215 | |
| 216 | int total = integral.intValueExact(); |
| 217 | int fraction = decimal.intValueExact(); |
| 218 | |
| 219 | if (fraction == 0) { |
| 220 | return ZonalOffset.ofTotalSeconds(total); |
| 221 | } else if (fraction == 1_000_000_000) { |
| 222 | return ZonalOffset.ofTotalSeconds(total + 1); |
| 223 | } else if (fraction == -1_000_000_000) { |
| 224 | return ZonalOffset.ofTotalSeconds(total - 1); |
| 225 | } else { |
| 226 | return new ZonalOffset(total, fraction); |
| 227 | } |
| 228 | |
| 229 | } |
| 230 | |
| 231 | /** |
| 232 | * <p>Creates a new shift based on a geographical longitude. </p> |