Bug 136312

Summary: Incorrect sunrise and icon for weather station in other timezone
Product: [Applications] kweather-kde3 Reporter: stefan.asserhall
Component: generalAssignee: geiseri
Status: RESOLVED FIXED    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Compiled Sources   
OS: Linux   
Latest Commit: Version Fixed In:
Attachments: Patch that fixes the bug

Description stefan.asserhall 2006-10-25 20:48:56 UTC
Version:           2.1.0 (using KDE KDE 3.5.5)
Installed from:    Compiled From Sources
Compiler:          gcc (GCC) 4.0.2 
OS:                Linux

The calculation of sunrise and sunset does not take into account cases where the weather station is in another timezone, which may cause the day to overlap with midnight local time. In this case the time can become greater than 24.00, which setHMS doesn't like.

The determination of night for displaying the icon also doesn't handle the case when the day overlaps with midnight correctly.

Patch attached.
Comment 1 stefan.asserhall 2006-10-25 20:50:09 UTC
Created attachment 18263 [details]
Patch that fixes the bug
Comment 2 Martin Koller 2006-12-25 16:10:29 UTC
SVN commit 616456 by mkoller:

BUG: 136312
BUG: 129679
BUG: 115920
BUG: 113339
BUG: 87642

Fix the calculation of sunrise/sunset and the calculation of
isNight.
Patch provided by J.O. Aho


 M  +18 -1     metar_parser.cpp  
 M  +26 -4     sun.cpp  


--- branches/KDE/3.5/kdetoys/kweather/metar_parser.cpp #616455:616456
@@ -411,6 +411,8 @@
 {
 #define E(t) ::pow(10, 7.5*t/(237.7+t))
 	float fRelHumidity = E(weatherInfo.dewC)/E(weatherInfo.tempC) * 100;
+        if (fRelHumidity > 100.0) fRelHumidity = 100.0; 
+
 	weatherInfo.qsRelHumidity.sprintf("%.1f", fRelHumidity);
 	removeTrailingDotZero(weatherInfo.qsRelHumidity);
 	weatherInfo.qsRelHumidity += "%";
@@ -841,7 +843,22 @@
 				longitude << " " << civilStart << " " << civilEnd << " " <<
 				m_localUTCOffset << endl;
 
-		return (currently < civilStart || currently > civilEnd);
+		if (civilStart != civilEnd)
+		{
+			if (civilEnd < civilStart)
+				/* Handle daylight past midnight in local time     */
+				/* for weather stations located at other timezones */
+				return (currently < civilStart && currently > civilEnd);
+			else
+				return (currently < civilStart || currently > civilEnd);
+		}
+		else
+		{
+			// Midnight Sun & Polar Night - In summer, the Sun is always 
+			// over the horizon line ... so use latitude & today date to 
+			// set isNight() value. 
+			return ((m_date.daysInYear() >= 80 || m_date.daysInYear() <= 264) && latitude.contains("S")); 
+		}
 	}
 }
 
--- branches/KDE/3.5/kdetoys/kweather/sun.cpp #616455:616456
@@ -204,20 +204,42 @@
 	QTime result;
 	
 	// Example:  say time is 17.7543  Then hours = 17 and minutes = 0.7543 * 60 = 45.258
+        // We need to convert the time to CORRECT local hours
 	int hours   = (int)floor(time);
+	int localhours = hours + (m_localUTCOffset / 60);
+
+	// We need to convert the time to CORRECT local minutes
 	int minutes = (int)floor((time - hours) * 60);
+	int localminutes = minutes + (m_localUTCOffset % 60);
 
-	int localhours = hours + (m_localUTCOffset / 60); 
-	if (localhours < 0) { localhours += 24; } 
-	if (localhours >= 24) { localhours -= 24; } 
+	// We now have to adjust the time to be within the 60m boundary
+	if (localminutes < 0)
+	{
+		//As minutes is less than 0, we need to
+		//reduce a hour and add 60m to minutes.
+		localminutes += 60;
+		localhours--;
+	}
+	if (localminutes >= 60)
+  {
+		//As minutes are more than 60, we need to
+		//add one more hour and reduce the minutes to
+		//a value between 0 and 59.
+		localminutes -= 60;
+		localhours++;
+	}
 
 	// Round up or down to nearest second.
 	// Use rint instead of nearbyint because rint is in FreeBSD
 	int seconds = (int)rint( fabs( minutes - ((time - hours) * 60) ) * 60 );
 
+	// We now have to adjust the time to be within the 24h boundary
+	if (localhours < 0) { localhours += 24; }
+	if (localhours >= 24) { localhours -= 24; }
+
 	// Try to set the hours, minutes and seconds for the local time.
 	// If this doesn't work, then we will return the invalid time.
-	result.setHMS( localhours, minutes + (m_localUTCOffset % 60), seconds );
+	result.setHMS( localhours, localminutes, seconds );
 
 	return result;	
 }