KosherJava Zmanim API Powering Many Mobile Apps

Mobile apps using Kosher Java Zmanim APIIn the past I posted about Android Zmanim, Jay Gindin’s open source Android zmanim project that uses the KosherJava Zmanim API. The fact that Android development uses Java natively means that it is very simple for Android developers to include zmanim in their apps. Since that time there have been a number of other applications (including iPhone apps) using the code. Moshe’s KosherCocoa Obj-C port of the KosherJava Zmanim API will probably result in additional iPhone apps that use the API. Yitzchok’s older Zmanim .NET port of the KosherJava Zmanim API also opened the door for Windows Phone zmanim applications as well (Ari Polski’s Zmaim app already uses it, and there are others in the works). I may post additional details about some of them in the future, including an updated post about Jay’s latest Android Zmanim release. I am aware of the following mobile applications that use the KosherJava Zmanim API.

There are also a few secular apps that are non-zmanim specific that use the API for sunrise and sunset calculations. One that I know of is Jeffrey Blattman’s Dawn to Dusk Widget, and I know that there are some photography apps that use it for sunrise/set calculations as well. There are likely more that I have missed, and a few that are in active development but unreleased. If you are aware of any missed apps, please let me know.

FAQ: Outputting Zmanim for A Different Time Zone With the the Zmanim API

Zmanim API FAQ

Question:

Why does the output of zmanim for a different time zone appear incorrect?

Answer:

One of the common issues encountered by developers using the API is that zmanim generated for a different time zone than the user’s time zone may return output that appears incorrect. For example a user in Lakewood, NJ trying to calculate sunrise for Yerushalayim may attempt to use the following code:

String locationName = "Jerusalem";
double latitude = 31.778; // Har habayis
double longitude = 35.2354;// Har Habayis
double elevation = 0;
TimeZone timeZone = TimeZone.getTimeZone("Asia/Jerusalem");
GeoLocation location = new GeoLocation(locationName, latitude, longitude, elevation, timeZone);
ZmanimCalendar zc = new ZmanimCalendar(location);
zc.getCalendar().set(2011, Calendar.FEBRUARY, 8);
System.out.println("Sunrise: " + zc.getSunrise());
System.out.println("Sunset: " + zc.getSunset());

While you would expect a sunrise of 6:27:41 AM and sunset of 5:19:19 PM, running this code on a computer anywhere in the Eastern Standard time zone would generate the following time that appears to be 7 hours early:

Sunrise: Mon Feb 07 23:27:41 EST 2011
Sunset: Tue Feb 08 10:19:19 EST 2011

The issue is simple, and the sunrise and sunset returned above are actually accurate. Zmanim are returned by the Zmanim API as a Java Date object that represents a moment in time (stored internally by Java as Unix Time – the number of milliseconds since the January 1, 1970 GMT). Sunrise in Yerushalayim on February 8th actually happens at 11:27:41 PM on February 7th EST. Java is simply outputting the Date as a String formatted to the users default time zone (EST in this example). The user probably intends to output the time in IST – Israel Standard Time (“Asia/Jerusalem” in the Olson database). To do this you have to output the zmanim using a formatter set to use the “Asia/Jerusalem” time zone.

DateFormat zmanimFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
zmanimFormat.setTimeZone(location.getTimeZone());

System.out.println("sunrise: " + zmanimFormat.format(zc.getSunrise()));
System.out.println("sunset:" + zmanimFormat.format(zc.getSunset()));

will output the expected

sunrise: Tue Feb 08 06:27:41 IST 2011
sunset:Tue Feb 08 17:19:19 IST 2011

Below is the full code example.

import net.sourceforge.zmanim.*;
import net.sourceforge.zmanim.util.*;
import java.util.TimeZone;
public class FormatZmanim{
	public static void main(String [] args) {
		String locationName = "Jerusalem";
		double latitude = 31.778; //latitude of Har habayis
		double longitude = 35.2354; //longitude of Har Habayis
		double elevation = 0; //optional elevation
		//use a Valid Olson Database timezone listed in java.util.TimeZone.getAvailableIDs()
		TimeZone timeZone = TimeZone.getTimeZone("Asia/Jerusalem");
		//create the location object
		GeoLocation location = new GeoLocation(locationName, latitude, longitude, elevation, timeZone);
		ZmanimCalendar zc = new ZmanimCalendar(location); //create the ZmanimCalendar
		zc.getCalendar().set(2011, Calendar.FEBRUARY, 8); //set the date
		DateFormat zmanimFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy"); //Create the formatter
		zmanimFormat.setTimeZone(location.getTimeZone()); //set the formatter's time zone
		System.out.println("sunrise: " + zmanimFormat.format(zc.getSunrise()));
		System.out.println("sunset:" + zmanimFormat.format(zc.getSunset()));
	}
}

Bearing to Yerushalayim and Zmanim Map 3.0

World mapThe Bearing to Yerushalayim and Zmanim Map was recently updated to version 3.0. This new release adds a number of new features to the Zmanim Map version 2.0 update released in March 2010. The main change was updating the Google Map API version from the deprecated v2 to v3. This change increases performance and adds much better support for mobile browsers. The upgrade also means that a Google Maps API key is no longer required. This makes it easy to drop it into any site without any configuration (contact me for details). Zmanim tab v3The technical notes on the original Technical Information about the Bearing to Yerushalayim Map post are still relevant, with very little having changed since the initial implementation.

The following is a partial list of the new features:

  • A number of additional zmanim in the More Zmanim tab, including tchilas and sof zman kiddush levana (if they occur on that day)
  • A link to download a 12 month Zmanim calendar directly from the map (using the same spreadsheet used in the Zmanim Calendar Generator). Clicking on the link from the Zmanim tab will generate a calendar with most typically used zmanim, while clicking on the link in the More Zmanim tab will download the full set of zmanim. These are available as the Calendar Type option in the Zmanim Calendar Generator
  • Increased use of jQuery and jQuery UI for formatting the zmanim tables to better match the site look & feel
  • Refactoring to make the code more robust and slightly more maintainable
  • Timezones for all of Israel now display the timezone of Asia/Jerusalem as opposed to the Asia/Gaza returned for parts of Israel by the GeoNames TimeZone web service

From a technical perspective there were a number of changes required due to updating the Google Maps API from v2 to v3. These include:

  • v3 no longer supports tabbed info windows, so the tabs are now implemented using jQuery UI
  • Renaming of a number of classes and functions such as GLatLng to LatLng
  • A number of functions that were part of API v2 were removed in v3. One example is the removal of radians in the LatLng that had been available as GLatLng.latRadians(). These missing functions required for the direction to Yerushalayim calculations are now supported in the Zmanim Map using prototypes

Zmanim API Ported to Cocoa / Objective-C

Port City JavaMoshe Berman completed the 2.0 release of his port of the KosherJava Zmanim API from Java to a Cocoa API using Objective-C. You can see the work in the KosherCocoa project page. The original work on the port dates back to Moshe’s iPhone Ultimate Omer 2 (iTunes link) app. In that app, he ported the minimum amount of code needed to calculate sunset in order to roll the day of the Omer after sunset. With Moshe’s latest check-in at github, he provided a port of a good portion of the API sticking to the basic design of the KosherJava API. The complexZmanimCalendar still remains to be ported, but the majority of zmanim in common use are in the ported ZmanimCalendar. Moshe’s blog post Introducing KosherCocoa 2.0 has additional details. Additional developer notes can be seen in the KosherCocoa wiki page. This port will be a boon to iOS developers who now have a simple way to include zmanim in their iPhone and iPad apps.
Here is some sample code that outputs zmanim to the console.

Zmanim.m

#import <Foundation/Foundation.h>
#import "ZmanimCalendar.h"

int main (int argc, const char * argv[]){

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    //  Set up the location
    NSString *locationName = @"Lakewood, NJ";
    double latitude = 40.096; //Lakewood, NJ
    double longitude = -74.222; //Lakewood, NJ
    NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:-18000];

    //  Initialize the Zmanim Calendar
    GeoLocation *geoLocation = [[GeoLocation alloc] initWithName:locationName andLatitude:latitude andLongitude:longitude andTimeZone:timeZone];
    ZmanimCalendar *zmanimCalendar = [[ZmanimCalendar alloc] initWithLocation:geoLocation];

    //  Create a Formatter for the date information
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setTimeZone:timeZone];
    [formatter setDateStyle:NSDateFormatterNoStyle];
    [formatter setTimeStyle:NSDateFormatterMediumStyle];

    NSDate *sunrise = [zmanimCalendar sunrise];
    NSDate *sofZmanShmaMGA = [zmanimCalendar sofZmanShmaMogenAvraham];
    NSDate *sofZmanShmaGRA = [zmanimCalendar sofZmanShmaGra];
    NSDate *sunset = [zmanimCalendar sunset];

    NSLog(@"Today's Zmanim for %@",  [geoLocation locationName]);
    NSLog(@"Sunrise: %@",  [formatter stringFromDate:sunrise]);
    NSLog(@"Sof Zman Shema MGA: %@",  [formatter stringFromDate:sofZmanShmaMGA]);
    NSLog(@"Sof Zman Shema GRA: %@",  [formatter stringFromDate:sofZmanShmaGRA]);
    NSLog(@"Sunset: %@",  [formatter stringFromDate:sunset]);

    [pool drain];
    return 0;
}

This would output (on February 8th):

Today's Zmanim for Lakewood, NJ
Sunrise: 6:58:43 AM
Sof Zman Shema MGA: 8:59:04 AM
Sof Zman Shema GRA: 9:35:04 AM
Sunset: 5:24:09 PM

Calculating Kiddush Levana Times Using the Zmanim API

Moon Crescent 3 Day LunationCalculating the earliest and latest times for Kiddush Levana has not been part of the KosherJava Zmanim API until now. This is because unlike other zmanim that solely rely on solar calculations that are tied to the Gregorian calendar, times for Kiddush Levanah depend on the Jewish calendar molad (lunar conjunction) computation. With the recent addition of Jewish calendar support to the alpha releases of the KosherJava Zmaim API 1.3, molad calculation was added, allowing for calculation of kidush levana times. Times include the earliest time calculated as 3 and 7 days after the molad. Sof zman kidush levanah includes the Maharil’s opinion that it is calculated as halfway between molad and molad, and the more lenient full 15 days from the molad mentioned by the Mechaber in the Shulchan Aruch. It should be noted that some opinions hold that the Rema who brings down the opinion of the Maharil’s of calculating half way between molad and molad is of the opinion that the Mechaber agrees with him. Also see the Aruch Hashulchan. For additional details on the subject, See Rabbi Dovid Heber’s very detailed writeup in Siman Daled (chapter 4) of Shaarei Zmanim.

Calculating the Molad

Kidush levanah times depend on the time of the molad. The time of the molad announced in shuls on Shabbos Mevarchim is the time of the Molad Emtzai (Average Molad) in Yerushalayim local mean time. This has to be converted to standard time. Standard time uses time zones to unify clock times across a large area. With 360° of longitude around the globe, the world is divided into 24 timezones (one per hour) resulting in timezones that are 15° of longitude each. Har Habayis with a longitude of 35.2354° is 5.2354° away from the 30° longitude line. Multiply the 5.235° by 4 minutes per degree (15° of longitude per hour) to reach 20.94 minutes, or 20 minutes and 56.496 seconds (5.235 * 4 = 20.94). This time is subtracted from the local molad time to arrive at Standard time. Since the time of the molad is at the same instant globally (unlike zmanim such as sunrise that depend on a person’s location), converting this to a user’s local time involves simply calculating the time difference between the time in Yerushalayim and your location. If daylight savings time is in use, this has to be added to the calculation. Java date formatting classes do this calculation on Date objects without forcing the developer to do any calculations.

Calculating the Start and End of Kiddush Levana Times

The JewishCalendar class contains the methods for claculating these zmanim. Calculating Tchilas Zman Kiddush Levana (the earliest time Kiddush Levana can be said) is done by adding 3 days or 7 days to the molad time. Sof Zman Kiddush Levana (the latest time Kiddush Levana can be said) is either the time between molad and molad calculated by adding 14 days, 18 hours, 22 minutes and 1.666 seconds to the molad (half the 29 days, 12 hours, 44 minutes and 1 chelek (3.333 seconds)), or by adding 15 days to the molad.

Using the Zmanim API Calculate Molad Based Times

Here is sample code for calculating various kiddush levana times for anywhere in the world for Shevat 5729 (1969). Since formatting classes requires a timezone for proper formatting, the simple code below assumes that you are looking for the time in your local timezone. If you want the time for a timezone other than the one your computer is in, set the SimpleDateFormat.setTimeZone() to the timezone you wish to display the times for.

int year = 5729;
int month = JewishDate.SHEVAT;
Date tchilas3Days = JewishCalendar.getTchilasZmanKidushLevanah3Days(year, month);
Date tchilas7Days = JewishCalendar.getTchilasZmanKidushLevanah7Days(year, month);
Date sofZmanBetweenMoldos = JewishCalendar.getSofZmanKidushLevanahBetweenMoldos(year, month);
Date sofZmanKidushLevanah15Days = JewishCalendar.getSofZmanKidushLevanah15Days(year, month);
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy 'at' HH:mm:ss z");
System.out.println("Tchilas Zman Kiddush Levana 3 Days: " + sdf.format(tchilas3Days));
System.out.println("Tchilas Zman Kiddush Levana 7 Days: " + sdf.format(tchilas7Days));
System.out.println("Sof Zman Kiddush Levana Between Moldos: " + sdf.format(sofZmanBetweenMoldos));
System.out.println("Sof Zman Kiddush Levana 15 Days: " + sdf.format(sofZmanKidushLevanah15Days));

this will output the following in an EST timezone.

Tchilas Zman Kiddush Levana 3 Days: Jan 21, 1969 at 06:06:29 EST
Tchilas Zman Kiddush Levana 7 Days: Jan 25, 1969 at 06:06:29 EST
Sof Zman Kiddush Levana Between Moldos: Feb 02, 1969 at 00:28:31 EST
Sof Zman Kiddush Levana 15 Days: Feb 02, 1969 at 06:06:29 EST

Kiddush Levana Times During Daylight Hours

As you can see, all of these times are at night (After tzais 72 and prior to Alos 72 minutes in Montreal). Many times, these calculations will result in times that are during daylight hours when Kidush Levana can’t be said. When using the API and calculating the time for the tchilas zman kiddush levana and the time is during daylight hours, the earliest time should be tzais the following night. When the calculated time of sof zman kiddush levana is during daylight hours, the time posted should be alos on the previous night. The API may at some point support a method of automatically calculating this.

KosherJava Zmanim API Released Under the LGPL License

LGPLUntil this point the KosherJava Zmanim API has been released under the GPL V2.0 open source license. This had the effect of forcing any application written using the library to release it’s source code under the same license. Being that the Zmanim API is a library, the LGPL is a more appropriate license. The LGPL allows developers to use the KosherJava Zmanim API, yet keep their application code closed source. Only changes to the API itself (such as ports to different languages) would have to be released as open source. I had in the past on request released the source under the LGPL (the Zmanim API .NET port has already been released under the LGPL with my permission), and with the recent 3/27/2011 SVN checkin I formally changed the Java Zmanim API license to the LGPL 2.1 (not the newer LGPL 3.0). The next 1.3.0 release will be the first formal release under the LGPL. In one case the change to the license required permission from developer who wrote code used by the the Zmanim API, and this was done.

Calculating Erev Pesach Zmanim

MatzahThe Zmanim API did not have dedicated zmanim to claculate the Erev Pesach zmanim of sof zman achilas chametz (the latest time one can eat chametz), and sof zman biur chametz (the latest time to burn chametz) till the April 14 check in to the KosherJava Zmanim Project GitHub repository. The latest time for eating chametz is at the end of the 4th hour of the day. This corresponds to sof zman tfila. The API has about 12 of those, so that does not require any special programming, but to help developers who are unaware of how they work I created 3 wrapper getSofZmanAchilasChametz methods (getSofZmanAchilasChametzGRA(), getSofZmanAchilasChametzMGA72Minutes() and getSofZmanAchilasChametzMGA16Point1Degrees()) calling the 3 most commonly used getSofZmanTfila methods (getSofZmanTfilaGRA(), getSofZmanTfilaMGA72Minutes() and getSofZmanTfilaMGA16Point1Degrees()). For example here is the exact code used in getSofZmanAchilasChametzGRA()

public Date getSofZmanAchilasChametzGRA() {
	return getSofZmanTfilaGRA();
}

The API itself is very flexible, and as long as you know the calculation of the zman, you can easily calculate it. For example, to calculate sof zman biur chametz according to the GR"A, the time would be 5 shaos zmaniyos after sunrise. Using the Zmanim API this would be coded as:

Date SofZmanBiurChametzGra = getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 5);

The exact code used in the API is:

public Date getSofZmanBiurChametzGRA() {
	return getTimeOffset(getSeaLevelSunrise(), getShaahZmanisGra() * 5);
}

Developers who want to use the current API to generate these zmanim can use the following sample as a guide.

String locationName = "Lakewood, NJ";
double latitude = 40.09596; //Lakewood, NJ
double longitude = -74.22213; //Lakewood, NJ
double elevation = 0; //optional elevation
TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
GeoLocation location = new GeoLocation(locationName, latitude, longitude, elevation, timeZone);
ComplexZmanimCalendar czc = new ComplexZmanimCalendar(location);
czc.getCalendar().set(Calendar.YEAR, 2011);
czc.getCalendar().set(Calendar.MONTH, Calendar.APRIL);
czc.getCalendar().set(Calendar.DAY_OF_MONTH, 18);
Date graAchilas = czc.getSofZmanTfilaGRA();
Date graBiur = czc.getTimeOffset(czc.getSeaLevelSunrise(), czc.getShaahZmanisGra() * 5);
Date mga72Achilas = czc.getSofZmanTfilaMGA72Minutes();
Date mga72Biur = czc.getTimeOffset(czc.getAlos72(), czc.getShaahZmanisMGA() * 5);
Date mga16Achilas = czc.getSofZmanTfilaMGA16Point1Degrees();
Date mga16Biur = czc.getTimeOffset(czc.getAlos16Point1Degrees(), czc.getShaahZmanis16Point1Degrees() * 5);
System.out.println("Erev Pesach Zmanim for " + locationName);
System.out.println("Sof Zman Achilas Chametz GRA: " + graAchilas);
System.out.println("Sof Zman Biur Chametz GRA: : " + graBiur);
System.out.println("Sof Zman Achilas Chametz MGA 72 Minutes: " + mga72Achilas);
System.out.println("Sof Zman Biur Chametz MGA 72 Minutes: " + mga72Biur);
System.out.println("Sof Zman Achilas Chametz MGA 16.1 Deg: " + mga16Achilas);
System.out.println("Sof Zman Biur Chametz MGA 16.1 Deg: " + mga16Biur);

this would output

C:\path\to\code>javac ErevPesachZmanim.java

C:\path\to\code>java ErevPesachZmanim

Erev Pesach Zmanim for Lakewood, NJ
Sof Zman Achilas Chametz GRA: Mon Apr 18 10:42:42 EDT 2011
Sof Zman Biur Chametz GRA: : Mon Apr 18 11:49:39 EDT 2011
Sof Zman Achilas Chametz MGA 72 Minutes: Mon Apr 18 10:18:42 EDT 2011
Sof Zman Biur Chametz MGA 72 Minutes: Mon Apr 18 11:37:39 EDT 2011
Sof Zman Achilas Chametz MGA 16.1 Deg: Mon Apr 18 10:13:56 EDT 2011
Sof Zman Biur Chametz MGA 16.1 Deg: Mon Apr 18 11:35:18 EDT 2011