Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>78.1</version>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down Expand Up @@ -111,6 +116,24 @@
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.7.0</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/dependency</outputDirectory>
<includeScope>compile</includeScope>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
Expand Down
27 changes: 15 additions & 12 deletions src/main/java/com/kosherjava/zmanim/AstronomicalCalendar.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
package com.kosherjava.zmanim;

import java.math.BigDecimal;
import java.util.Calendar;
import com.ibm.icu.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import com.ibm.icu.util.TimeZone;

import com.kosherjava.zmanim.util.AstronomicalCalculator;
import com.kosherjava.zmanim.util.GeoLocation;
Expand Down Expand Up @@ -49,7 +49,7 @@
* double longitude = -74.2094; // Lakewood, NJ
* double elevation = 20; // optional elevation correction in Meters
* // the String parameter in getTimeZone() has to be a valid timezone listed in
* // {@link java.util.TimeZone#getAvailableIDs()}
* // {@link com.ibm.icu.util.TimeZone#getAvailableIDs()}
* TimeZone timeZone = TimeZone.getTimeZone(&quot;America/New_York&quot;);
* GeoLocation location = new GeoLocation(locationName, latitude, longitude, elevation, timeZone);
* AstronomicalCalendar ac = new AstronomicalCalendar(location);
Expand Down Expand Up @@ -350,6 +350,7 @@ public Date getSunriseOffsetByDegrees(double offsetZenith) {
*/
public Date getSunsetOffsetByDegrees(double offsetZenith) {
double sunset = getUTCSunset(offsetZenith);
// System.out.println("Jsunset: " + sunset);
if (Double.isNaN(sunset)) {
return null;
} else {
Expand Down Expand Up @@ -626,8 +627,9 @@ protected Date getDateFromTime(double time, SolarEvent solarEvent) {
return null;
}
double calculatedTime = time;

Calendar adjustedCalendar = getAdjustedCalendar();

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.clear();// clear all fields
cal.set(Calendar.YEAR, adjustedCalendar.get(Calendar.YEAR));
Expand All @@ -637,10 +639,10 @@ protected Date getDateFromTime(double time, SolarEvent solarEvent) {
int hours = (int) calculatedTime; // retain only the hours
calculatedTime -= hours;
int minutes = (int) (calculatedTime *= 60); // retain only the minutes
calculatedTime -= minutes;
calculatedTime -= minutes;
int seconds = (int) (calculatedTime *= 60); // retain only the seconds
calculatedTime -= seconds; // remaining milliseconds

// Check if a date transition has occurred, or is about to occur - this indicates the date of the event is
// actually not the target date, but the day prior or after
int localTimeHours = (int)getGeoLocation().getLongitude() / 15;
Expand Down Expand Up @@ -758,8 +760,9 @@ public Date getLocalMeanTime(double hours) {
if (hours < 0 || hours >= 24) {
throw new IllegalArgumentException("Hours must between 0 and 23.9999...");
}
return getTimeOffset(getDateFromTime(hours - getGeoLocation().getTimeZone().getRawOffset()
/ (double) HOUR_MILLIS, SolarEvent.SUNRISE), -getGeoLocation().getLocalMeanTimeOffset());
long timezoneOffsetMillis = getCalendar().getTimeZone().getOffset(getCalendar().getTimeInMillis());
return getTimeOffset(getDateFromTime(hours - timezoneOffsetMillis
/ (double) HOUR_MILLIS, SolarEvent.SUNRISE), -getGeoLocation().getLocalMeanTimeOffset(calendar));
}

/**
Expand All @@ -769,11 +772,11 @@ public Date getLocalMeanTime(double hours) {
* @return the adjusted Calendar
*/
private Calendar getAdjustedCalendar(){
int offset = getGeoLocation().getAntimeridianAdjustment();
int offset = getGeoLocation().getAntimeridianAdjustment(getCalendar());
if (offset == 0) {
return getCalendar();
}
Calendar adjustedCalendar = (Calendar) getCalendar().clone();
Calendar adjustedCalendar = getCalendar().clone();
adjustedCalendar.add(Calendar.DAY_OF_MONTH, offset);
return adjustedCalendar;
}
Expand Down Expand Up @@ -900,10 +903,10 @@ public void setCalendar(Calendar calendar) {

/**
* A method that creates a <a href="https://en.wikipedia.org/wiki/Object_copy#Deep_copy">deep copy</a> of the object.
* <b>Note:</b> If the {@link java.util.TimeZone} in the cloned {@link com.kosherjava.zmanim.util.GeoLocation} will
* <b>Note:</b> If the {@link com.ibm.icu.util.TimeZone} in the cloned {@link com.kosherjava.zmanim.util.GeoLocation} will
* be changed from the original, it is critical that
* {@link com.kosherjava.zmanim.AstronomicalCalendar#getCalendar()}.
* {@link java.util.Calendar#setTimeZone(TimeZone) setTimeZone(TimeZone)} be called in order for the
* {@link com.ibm.icu.util.Calendar#setTimeZone(TimeZone) setTimeZone(TimeZone)} be called in order for the
* AstronomicalCalendar to output times in the expected offset after being cloned.
*
* @see java.lang.Object#clone()
Expand Down
24 changes: 14 additions & 10 deletions src/main/java/com/kosherjava/zmanim/ComplexZmanimCalendar.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package com.kosherjava.zmanim;

import java.util.Calendar;
import com.ibm.icu.util.Calendar;
import java.util.Date;
import com.kosherjava.zmanim.util.AstronomicalCalculator;
import com.kosherjava.zmanim.util.GeoLocation;
Expand All @@ -40,7 +40,7 @@
* double longitude = -74.222; // Lakewood, NJ
* double elevation = 20; // optional elevation correction in Meters
* // the String parameter in getTimeZone() has to be a valid time zone listed in
* // {@link java.util.TimeZone#getAvailableIDs()}
* // {@link com.ibm.icu.util.TimeZone#getAvailableIDs()}
* TimeZone timeZone = TimeZone.getTimeZone(&quot;America/New_York&quot;);
* GeoLocation location = new GeoLocation(locationName, latitude, longitude, elevation, timeZone);
* ComplexZmanimCalendar czc = new ComplexZmanimCalendar(location);
Expand Down Expand Up @@ -3486,18 +3486,22 @@ public Date getSofZmanKidushLevanaBetweenMoldos(Date alos, Date tzais) {
*/
private Date getMoladBasedTime(Date moladBasedTime, Date alos, Date tzais, boolean techila) {
Date lastMidnight = getMidnightLastNight();
Date midnightTonight = getMidnightTonight();
if (!(moladBasedTime.before(lastMidnight) || moladBasedTime.after(midnightTonight))){
if (alos != null || tzais != null) {
if (techila && !(moladBasedTime.before(tzais) || moladBasedTime.after(alos))){
Date midnightTonight = getMidnightTonight();
if(moladBasedTime.before(lastMidnight) || moladBasedTime.after(midnightTonight)){ // Invalid time, bailout
return null;
} else if (alos == null || tzais == null){ // Not enough info to adjust
return moladBasedTime;
} else { // It's the daytime, get the next/prev night
if (moladBasedTime.after(alos) && moladBasedTime.before(tzais)) {
if (techila) {
return tzais;
} else {
return alos;
}
}
return moladBasedTime;
}
return null;
} else { // It's the night, the provided time is valid
return moladBasedTime;
}
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/kosherjava/zmanim/ZmanimCalendar.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package com.kosherjava.zmanim;

import java.util.Calendar;
import com.ibm.icu.util.Calendar;
import java.util.Date;

import com.kosherjava.zmanim.hebrewcalendar.JewishCalendar;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
import com.kosherjava.zmanim.util.GeoLocation;

import java.time.LocalDate;
import java.util.Calendar;
import com.ibm.icu.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import com.ibm.icu.util.TimeZone;

/**
* The JewishCalendar extends the JewishDate class and adds calendar methods.
Expand All @@ -39,7 +39,7 @@
* </ol>
*
* @see java.util.Date
* @see java.util.Calendar
* @see com.ibm.icu.util.Calendar
* @author &copy; Y. Paritcher 2019 - 2022
* @author &copy; Avrom Finkelstien 2002
* @author &copy; Eliyahu Hershfeld 2011 - 2024
Expand Down Expand Up @@ -264,7 +264,7 @@ public JewishCalendar(Date date) {
}

/**
* A constructor that initializes the date to the {@link java.util.Calendar Calendar} parameter.
* A constructor that initializes the date to the {@link com.ibm.icu.util.Calendar Calendar} parameter.
*
* @param calendar
* the <code>Calendar</code> to set the calendar to
Expand Down Expand Up @@ -1249,7 +1249,7 @@ public Date getMoladAsDate() {
molad.getMoladHours(), molad.getMoladMinutes(), (int) moladSeconds);
cal.set(Calendar.MILLISECOND, (int) (1000 * (moladSeconds - (int) moladSeconds)));
// subtract local time difference of 20.94 minutes (20 minutes and 56.496 seconds) to get to Standard time
cal.add(Calendar.MILLISECOND, -1 * (int) geo.getLocalMeanTimeOffset());
cal.add(Calendar.MILLISECOND, -1 * (int) geo.getLocalMeanTimeOffset(cal));
return cal.getTime();
}

Expand Down
71 changes: 44 additions & 27 deletions src/main/java/com/kosherjava/zmanim/hebrewcalendar/JewishDate.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@

import java.time.LocalDate;
import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.TimeZone;

/**
* The JewishDate is the base calendar class, that supports maintenance of a {@link java.util.GregorianCalendar}
* The JewishDate is the base calendar class, that supports maintenance of a {@link com.ibm.icu.util.GregorianCalendar}
* instance along with the corresponding Jewish date. This class can use the standard Java Date and Calendar
* classes for setting and maintaining the dates, but it does not subclass these classes or use them internally
* in any calculations. This class also does not have a concept of a time (which the Date class does). Please
Expand Down Expand Up @@ -50,7 +51,7 @@
* @see JewishCalendar
* @see HebrewDateFormatter
* @see java.util.Date
* @see java.util.Calendar
* @see com.ibm.icu.util.Calendar
* @author &copy; Avrom Finkelstien 2002
* @author &copy; Eliyahu Hershfeld 2011 - 2024
*/
Expand Down Expand Up @@ -567,8 +568,8 @@ private static int getJewishMonthOfYear(int year, int month) {
* @param month
* the Jewish month to validate. It will reject a month &lt; 1 or &gt; 12 (or 13 on a leap year) .
* @param dayOfMonth
* the day of the Jewish month to validate. It will reject any value &lt; 1 or &gt; 30 TODO: check calling
* methods to see if there is any reason that the class can validate that 30 is invalid for some months.
* the day of the Jewish month to validate. It will reject any value &lt; 1 or &gt; the number of days in the month
* for that year.
* @param hours
* the hours (for <em>molad</em> calculations). It will reject an hour &lt; 0 or &gt; 23
* @param minutes
Expand All @@ -590,9 +591,12 @@ private static void validateJewishDate(int year, int month, int dayOfMonth, int
throw new IllegalArgumentException("The Jewish month has to be between 1 and 12 (or 13 on a leap year). "
+ month + " is invalid for the year " + year + ".");
}
if (dayOfMonth < 1 || dayOfMonth > 30) {
throw new IllegalArgumentException("The Jewish day of month can't be < 1 or > 30. " + dayOfMonth
+ " is invalid.");

int maxDaysInMonth = getDaysInJewishMonth(month, year);

if (dayOfMonth < 1 || dayOfMonth > maxDaysInMonth) {
throw new IllegalArgumentException("The Jewish day of month can't be < 1 or > " + maxDaysInMonth + ". " + dayOfMonth
+ " is invalid for the month " + month + " of the year " + year + ".");
}
// reject dates prior to 18 Teves, 3761 (1/1/1 AD). This restriction can be relaxed if the date coding is
// changed/corrected
Expand Down Expand Up @@ -986,7 +990,7 @@ public JewishDate(Date date) {
}

/**
* A constructor that initializes the date to the {@link java.util.Calendar Calendar} parameter.
* A constructor that initializes the date to the {@link com.ibm.icu.util.Calendar Calendar} parameter.
*
* @param calendar
* the <code>Calendar</code> to set the calendar to
Expand All @@ -1010,7 +1014,7 @@ public JewishDate(LocalDate localDate) {
}

/**
* Sets the date based on a {@link java.util.Calendar Calendar} object. Modifies the Jewish date as well.
* Sets the date based on a {@link com.ibm.icu.util.Calendar Calendar} object. Modifies the Jewish date as well.
*
* @param calendar
* the <code>Calendar</code> to set the calendar to
Expand Down Expand Up @@ -1174,13 +1178,18 @@ public void setJewishDate(int year, int month, int dayOfMonth, int hours, int mi
}

/**
* Returns this object's date as a {@link java.util.Calendar} object.
* Returns this object's date as a {@link com.ibm.icu.util.Calendar} object.
*
* @return The {@link java.util.Calendar}
* @return The {@link com.ibm.icu.util.Calendar}
*/
public Calendar getGregorianCalendar() {
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
calendar.set(getGregorianYear(), getGregorianMonth(), getGregorianDayOfMonth());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar;
}

Expand Down Expand Up @@ -1219,7 +1228,7 @@ public String toString() {
*
* <pre>
* <code>
* Calendar cal = jewishDate.getTime(); // get a java.util.Calendar representation of the JewishDate
* Calendar cal = jewishDate.getTime(); // get a com.ibm.icu.util.Calendar representation of the JewishDate
* cal.add(Calendar.MONTH, 3); // add 3 Gregorian months
* jewishDate.setDate(cal); // set the updated calendar back to this class
* </code>
Expand Down Expand Up @@ -1292,28 +1301,36 @@ public void forward(int field, int amount) {
}

/**
* Forward the Jewish date by the number of months passed in.
* FIXME: Deal with forwarding a date such as 30 Nissan by a month. 30 Iyar does not exist. This should be dealt with similar to
* the way that the Java Calendar behaves (not that simple since there is a difference between add() or roll().
* Advances the Jewish date forward by the specified number of months.
* If the day doesn't exist in the target month (e.g., 30 Iyar), it adjusts to the last day of that month (29 Iyar).
*
* @throws IllegalArgumentException if the amount is less than 1
* @param amount the number of months to roll the month forward
* @param amount the number of months to advance (must be at least 1)
*/
private void forwardJewishMonth(int amount) {
if (amount < 1) {
throw new IllegalArgumentException("the amount of months to forward has to be greater than zero.");
}
int currentMonth = getJewishMonth();
int currentYear = getJewishYear();
int currentDay = getJewishDayOfMonth();
for (int i = 0; i < amount; i++) {
if (getJewishMonth() == ELUL) {
setJewishMonth(TISHREI);
setJewishYear(getJewishYear() + 1);
} else if ((! isJewishLeapYear() && getJewishMonth() == ADAR)
|| (isJewishLeapYear() && getJewishMonth() == ADAR_II)){
setJewishMonth(NISSAN);
boolean isLeapYear = JewishDate.isJewishLeapYear(currentYear);
if (currentMonth == ELUL) {
currentMonth = TISHREI;
currentYear = currentYear + 1;
} else if ((!isLeapYear && currentMonth == ADAR)
|| (isLeapYear && currentMonth == ADAR_II)){
currentMonth = NISSAN;
} else {
setJewishMonth(getJewishMonth() + 1);
currentMonth = currentMonth + 1;
}
}
int maxDaysInMonth = JewishDate.getDaysInJewishMonth(currentMonth, currentYear);
if (currentDay > maxDaysInMonth) {
currentDay = maxDaysInMonth;
}
setJewishDate(currentYear, currentMonth, currentDay);
}

/**
Expand All @@ -1324,7 +1341,7 @@ private void forwardJewishMonth(int amount) {
*
* <pre>
* <code>
* Calendar cal = jewishDate.getTime(); // get a java.util.Calendar representation of the JewishDate
* Calendar cal = jewishDate.getTime(); // get a com.ibm.icu.util.Calendar representation of the JewishDate
* cal.add(Calendar.MONTH, -3); // subtract 3 Gregorian months
* jewishDate.setDate(cal); // set the updated calendar back to this class
* </code>
Expand Down Expand Up @@ -1398,7 +1415,7 @@ public int compareTo(JewishDate jewishDate) {
/**
* Returns the Gregorian month (between 0-11).
*
* @return the Gregorian month (between 0-11). Like the java.util.Calendar, months are 0 based.
* @return the Gregorian month (between 0-11). Like the com.ibm.icu.util.Calendar, months are 0 based.
*/
public int getGregorianMonth() {
return gregorianMonth - 1;
Expand Down
Loading