Bug 115920

Summary: Displays night icon at noon with complex timezone settings
Product: [Applications] kweather-kde3 Reporter: guanx <guanx.bac>
Component: generalAssignee: geiseri
Status: RESOLVED FIXED    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Slackware   
OS: Linux   
Latest Commit: Version Fixed In:

Description guanx 2005-11-08 14:27:07 UTC
Version:            (using KDE KDE 3.4.2)
Installed from:    Slackware Packages
OS:                Linux

I set my timezone to GMT+0800 to display the time for my home town, while I myself am in GMT+0100. I'm syncing my computer's clock with a local (GMT+0100) time server every hour and it displays correct local time for GMT+0800. There is no problem. KWeather reports sunrise and sunset times in local time for GMT+0800 as sunrise at 14:35 and sunset at 23:54. That's okay. The problem is, although the last update time (20:20 for GMT+0800) is between sunrise and sunset, KWeather displays a night icon. So I find myself sync to the right clock, in the mid-day sunshine and saw a night icon.
You can goto the following URL to see my screenshot.
http://www.newsmth.net/bbscon.php?bid=392&id=296455&ap=429
Comment 1 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;	
 }