Victor Thompson has proposed merging lp:~vthompson/ubuntu-weather-app/reboot-sunrise-sunset into lp:ubuntu-weather-app/reboot.
Commit message: Use sunrise/sunset from API if available, otherwise use calculated times Requested reviews: Ubuntu Weather Developers (ubuntu-weather-dev) For more details, see: https://code.launchpad.net/~vthompson/ubuntu-weather-app/reboot-sunrise-sunset/+merge/263171 Use sunrise/sunset from API if available, otherwise use calculated times -- Your team Ubuntu Weather Developers is requested to review the proposed merge of lp:~vthompson/ubuntu-weather-app/reboot-sunrise-sunset into lp:ubuntu-weather-app/reboot.
=== modified file 'app/components/DayDelegate.qml' --- app/components/DayDelegate.qml 2015-06-21 14:02:58 +0000 +++ app/components/DayDelegate.qml 2015-06-26 21:53:18 +0000 @@ -224,13 +224,13 @@ ForecastDetailsDelegate { id: sunriseForecast forecast: i18n.tr("Sunrise") - // FIXME: need icon + imageName: "info" } ForecastDetailsDelegate { id: sunsetForecast forecast: i18n.tr("Sunset") - // FIXME: need icon + imageName: "info" } } } === modified file 'app/components/ForecastDetailsDelegate.qml' --- app/components/ForecastDetailsDelegate.qml 2015-06-21 15:02:05 +0000 +++ app/components/ForecastDetailsDelegate.qml 2015-06-26 21:53:18 +0000 @@ -24,6 +24,7 @@ spacing: units.gu(2) visible: value !== "" + property alias imageName: icon.name property alias imageSource: icon.source property alias forecast: forecastLabel.text property alias value: forecastValue.text === modified file 'app/data/WeatherApi.js' --- app/data/WeatherApi.js 2015-04-27 00:57:35 +0000 +++ app/data/WeatherApi.js 2015-06-26 21:53:18 +0000 @@ -512,6 +512,7 @@ "daily": combinedData[0]["DailyForecasts"], "forecast": combinedData[0]["HourlyForecasts"], "current": combinedData[0]["StandardObservation"], + "sunRiseSet": combinedData[0]["SunRiseSet"], }; print("["+location.name+"] "+JSON.stringify(localNow)); // add openweathermap id for faster responses @@ -522,6 +523,7 @@ for(var x=0;x<5;x++) { var dayData = data["daily"][x], date = getLocationTime(((dayData.validDate*1000)-1000)+offset); // minus 1 sec to handle +/-12 TZ + var sunRiseSet = data["sunRiseSet"][x]; day = date.year+"-"+date.month+"-"+date.date; if(!todayDate) { if(localNow.year+"-"+localNow.month+"-"+localNow.date > day) { @@ -531,6 +533,10 @@ todayDate = date; } tmpResult[day] = _buildDayFormat(date, dayData, nowMs); + var sunrise = new Date(sunRiseSet.rise*1000); + var sunset = new Date(sunRiseSet.set*1000); + tmpResult[day].sunrise = sunrise.toLocaleTimeString(); + tmpResult[day].sunset = sunset.toLocaleTimeString(); } // if(data["forecast"] !== undefined) { === added file 'app/data/suncalc.js' --- app/data/suncalc.js 1970-01-01 00:00:00 +0000 +++ app/data/suncalc.js 2015-06-26 21:53:18 +0000 @@ -0,0 +1,300 @@ +/* + (c) 2011-2014, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/mooon position and light phases. + https://github.com/mourner/suncalc +*/ + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + +function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } +function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } + +function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } + + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date and latitude/longitude + +SunCalc.getTimes = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + + Jset = getSetJ(time[0] * rad, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec); + + // altitude correction for refraction + h = h + rad * 0.017 / tan(h + rad * 10.26 / (h + rad * 5.10)); + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist + }; +}; + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +}; + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng) { + var t = new Date(date); + t.setHours(0); + t.setMinutes(0); + t.setSeconds(0); + t.setMilliseconds(0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +}; + + +// export as AMD module / Node module / browser variable +//if (typeof define === 'function' && define.amd) define(SunCalc); +//else if (typeof module !== 'undefined') module.exports = SunCalc; +//else window.SunCalc = SunCalc; + +//}()); === modified file 'app/ui/LocationPane.qml' --- app/ui/LocationPane.qml 2015-06-21 14:02:58 +0000 +++ app/ui/LocationPane.qml 2015-06-26 21:53:18 +0000 @@ -20,6 +20,7 @@ import Ubuntu.Components 1.2 import Ubuntu.Components.ListItems 0.1 as ListItem import "../components" +import "../data/suncalc.js" as SunCalc Item { id: locationItem @@ -99,6 +100,8 @@ image: (forecasts[x].icon !== undefined && iconMap[forecasts[x].icon] !== undefined) ? iconMap[forecasts[x].icon] : "", chanceOfRain: forecasts[x].propPrecip === undefined ? -1 : forecasts[x].propPrecip, humidity: emptyIfUndefined(forecasts[x].humidity, "%"), + sunrise: forecasts[x].sunrise || SunCalc.SunCalc.getTimes(new Date(), data.location.coord.lat, data.location.coord.lon).sunrise.toLocaleTimeString(), + sunset: forecasts[x].sunset || SunCalc.SunCalc.getTimes(new Date(), data.location.coord.lat, data.location.coord.lon).sunset.toLocaleTimeString(), uvIndex: emptyIfUndefined(forecasts[x].uv), wind: forecasts[x][tempUnits].windSpeed === undefined || forecasts[x].windDir === undefined ? "" : Math.round(forecasts[x][tempUnits].windSpeed) + settings.windUnits + " " + forecasts[x].windDir @@ -185,8 +188,8 @@ humidity: model.humidity // TODO: extra from API //pollen: model.pollen - //sunrise: model.sunrise - //sunset: model.sunset + sunrise: model.sunrise + sunset: model.sunset wind: model.wind uvIndex: model.uvIndex }
-- Mailing list: https://launchpad.net/~ubuntu-touch-coreapps-reviewers Post to : ubuntu-touch-coreapps-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~ubuntu-touch-coreapps-reviewers More help : https://help.launchpad.net/ListHelp