Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to Display Web Visitor's Sunrise and Sunset Time by IP Address

0.00/5 (No votes)
10 Apr 2014 1  
Display visitor's sunrise and sunset time based on their IP address using C#

Introduction

Weather forecast websites like to display sunrise and sunset time along with other weather related information. If you have ever wondered how they are able to get the time that the sun rises and sets, then you should read further.

This tip will demonstrate how to calculate a website visitor's sunrise and sunset time based on their IP address. In order to get the sunrise and sunset time, we need the Time Zone, Longitude and Latitude information. Thanks to free IP2Location Lite database, we can get the three bits of information.

Using the Code

This tip assumes that you are familiar with basic HTML code, ASP.NET code and MySQL. I will show you how to translate the IP address to IP numbers so that I can query the IP database from IP2Location Lite (DB11) before we calculate the time.

Remember to unzip the database file after you have downloaded the zip file. Follow the instructions in order to create a database table.

Let's start off with the sunset_sunrise.aspx file which is displayed below.

<%@ Page Language="C#" AutoEventWireup="true" 
CodeBehind="sunset_sunrise.aspx.cs" Inherits="SunsetSunrise.sunset_sunrise" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <%
        string ip_addr = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
        if (ip_addr == "" || ip_addr == null)
        {
            ip_addr = Request.ServerVariables["REMOTE_ADDR"];
        }
        
        long ip_num = ip_to_number(ip_addr);
        string query = "SELECT time_zone, country_code, latitude, longitude FROM db11lite 
        WHERE " + ip_num + ">= ip_from AND " + ip_num + " <= ip_to";
        string[] data = Get_Data(query);
        if (data[0].Equals("-"))
        {
            data[0] = "0:00";
            data[1] = "-";
            data[2] = "0";
            data[3] = "0";
        }
        
        string[] separator = {":"};
        string[] offset = data[0].Split(separator, StringSplitOptions.None); 
        double off = Convert.ToDouble(offset[0]);
        c_sunset_sunrise(Convert.ToDouble(data[3]), Convert.ToDouble(data[2]));
        DateTime day = DateTime.UtcNow;
        day = day.AddHours(off);
        string sunset = calculate(day, 0, off);
        string sunrise = calculate(day, 1, off);
    %>

    <ul>
        <li>Time Zone: <%Response.Write(data[0]); %></li>
        <li>Country Code: <%Response.Write(data[1]); %></li>
        <li>Latitude: <%Response.Write(data[2]); %></li>
        <li>Longitude: <%Response.Write(data[3]); %></li>
        <li>Sun Set Time: <%Response.Write(sunset); %></li>
        <li>Sun Rise Time: <%Response.Write(sunrise); %></li>
    </ul>
    </div>
    </form>
</body>
</html>

The actual code that does all the work will be at sunset_sunrise.aspx.cs file.

When a visitor visit your page, it will call the ip_to_number function to convert their IP address into IP numbers and then retrieve the Time Zone, Latitude, Longitude information from the database.

The code looks like this.

Converting IP Address to IP Number

public long ip_to_number(string ip_addr)
    {
        string[] ip_Sblock;
        int[] ip_block = new int[4];
        string[] separator = { "." };

        ip_Sblock = ip_addr.Split(separator, StringSplitOptions.None);
        for (int i = 0; i <= 3; i++)
        {
            ip_block[i] = Convert.ToInt32(ip_Sblock[i]);
        }

        return ip_block[0] * 16777216 + ip_block[1] * 65536 + ip_block[2] * 256 + ip_block[3];
    } 

After you get the IP numbers, pass the SQL statement to the Get_Data function and it will return the database data in a datatable.

Retrieving Time Zone, Longitude, Latitude Information

public static string[] Get_Data(string query)
    {
        //Database connection string, replace lower capital with MySQL settings
        string db_con_string = "SERVER=server;DATABASE=database;UID=userid;PASSWORD=password;";
        using (MySqlConnection con = new MySqlConnection(db_con_string))
        {
            using (MySqlCommand cmd = new MySqlCommand())
            {
                cmd.CommandText = query;
                using (MySqlDataAdapter sda = new MySqlDataAdapter())
                {
                    cmd.Connection = con;
                    sda.SelectCommand = cmd;
                    using (DataSet ds = new DataSet())
                    {
                        DataTable dt = new DataTable();
                        sda.Fill(dt);
                        object timezone = dt.Rows[0]["time_zone"];
                        object country_code = dt.Rows[0]["country_code"];
                        object latitude = dt.Rows[0]["latitude"];
                        object longitude = dt.Rows[0]["longitude"];
                        string[] data = { Convert.ToString(timezone), 
                        Convert.ToString(country_code), Convert.ToString(latitude), Convert.ToString(longitude) };
                        return data;
                    }
                }
            }
        }
    }

Now, it will pass the data to the calculate function and return the sunrise and sunset time after the calculation.

Calculation for Sunrise and Sunset Time

protected string calculate(DateTime date, int set_rise, double offset)
        {
            //Convert longitude into hour value
            double long_hour = longitude / 15;
            double t = 0;

            //sunset = 0, sunrise = 1
            //calculate approximate time
            if (set_rise == 1)
            {
                t = Convert.ToDouble(date.DayOfYear) + ((6 - long_hour) / 24);
            }
            else if (set_rise == 0)
            {
                t = Convert.ToDouble(date.DayOfYear) + ((18 - long_hour) / 24);
            }

            //Calculate Sun's mean anomaly time
            double mean = (0.9856 * t) - 3.289;

            //Calculate Sun's true longitude
            double sun_true_long = mean + (1.916 * Math.Sin(mean * D2R)) + (0.020 * Math.Sin(2 * mean * D2R)) + 282.634;
            if (sun_true_long > 360)
                sun_true_long = sun_true_long - 360;
            else if (sun_true_long < 0)
                sun_true_long = sun_true_long + 360;

            //Calculate Sun's right ascension
            double right_ascension = R2D * Math.Atan(0.91764 * Math.Tan(sun_true_long * D2R));
            if (right_ascension > 360)
                right_ascension = right_ascension - 360;
            else if (right_ascension < 0)
                right_ascension = right_ascension + 360;

            //Adjust right ascension value to be in the same quadrant as Sun's true longitude
            double Lquadrant = (Math.Floor(sun_true_long / 90)) * 90;
            double RAquadrant = (Math.Floor(right_ascension / 90)) * 90;
            right_ascension = right_ascension + (Lquadrant - RAquadrant);

            //Convert right ascension value into hours
            right_ascension = right_ascension / 15;

            //Calculate Sun's declination
            double sinDec = 0.39782 * Math.Sin(sun_true_long * D2R);
            double cosDec = Math.Cos(Math.Asin(sinDec));

            //Setting Sun's zenith value
            double zenith = 90 + (50 / 60);

            //Calculate Sun's local hour angle
            double cosH = (Math.Cos(zenith * D2R) - (sinDec * Math.Sin(latitude * D2R))) / (cosDec * Math.Cos(latitude * D2R));

            if (cosH > 1)
            {
                Response.Write("Sun never rises on this day. " + date.Year + 
                "/" + date.Month + "/" + date.Day + "<br>");
            }
            else if (cosH < -1)
            {
                Response.Write("Sun never sets on this day. " + date.Year + 
                "/" + date.Month + "/" + date.Day + "<br>");
            }

            //Calculate and convert into hour of sunset or sunrise
            double hour = 0;
            if (set_rise == 1)
            {
                hour = 360 - R2D * Math.Acos(cosH);
            }
            else if (set_rise == 0)
            {
                hour = R2D * Math.Acos(cosH);
            }

            hour = hour / 15;

            //Calculate local mean time of rising or setting
            double local_mean_time = hour + right_ascension - (0.06571 * t) - 6.622;

            //Adjust time to UTC
            double utc = local_mean_time - long_hour;
            
            //Convert time from UTC to local time zone
            double local_time = utc + offset;
            if (local_time > 24)
                local_time = local_time - 24;
            else if (local_time < 0)
                local_time = local_time + 24;

            //Convert the local_time into time format
            int s_hour = Convert.ToInt32(Math.Floor(local_time));
            int s_minute = Convert.ToInt32((local_time - s_hour) * 60);

            if (s_minute < 10)
                return s_hour + ":0" + s_minute;
            else
                return s_hour + ":" + s_minute;           
        } 

If you look into the code carefully, you will see some comments before calculations. Further explanation here.

  • Calculate the Sun's Mean Anomaly: The Sun’s mean anomaly determines the Sun’s position on a circular orbit rather than the true elliptical orbit.
  • Calculate the Sun’s Right Ascension and Declination: The equatorial coordinate system is a system used for mapping the position of objects in the sky. This system projects the object onto an imaginary sphere, called the celestial sphere. The coordinates of this system are Right Ascension (the celestial equivalent of Longitude) and Declination (the celestial equivalent to Latitude).
  • Calculate the Sun’s Local Hour Angle: The Sun's hour angle is determined from the latitude and the zenith value for the type of sunrise or sunset time being calculated. The different types are described below.
  • Calculate the Sun’s Local Hour Angle: The Sun's hour angle is determined from the latitude and the zenith value for the type of sunrise or sunset time being calculated. The different types are described below.
  • Calculate the Local Mean Time of Sunset or Sunset: The UTC time of the sunset or sunrise is calculated using the hour angle, right ascension and longitudinal adjustment.
  • Adjust for Local Time: A time zone offset is used to adjust for local time

For more information on the algorithm used to calculate the sunrise and sunset, you can refer to the following sites:

  1. http://en.wikipedia.org/wiki/Sunrise_equation
  2. http://williams.best.vwh.net/sunrise_sunset_algorithm.htm
  3. http://www.micromegacorp.com/downloads/documentation/AN038-Sunrise%20Sunset.pdf.

Points of Interest

*Calculation part is not hard, is a fixed algorithm after all.

History

  • 3rd April, 2014: Initial version
  • 10th April, 2014: Updated version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here