Search code examples
javascriptunix-timestampopenweathermap

Is there other ways to convert Unix timestamp to local time in javascript with openWeather API timezone involved?


I’m using the OpenWeather API to create a simple web page that displays dynamic weather data, including sunrise and sunset times. The API provides these times in seconds (Unix timestamp), and I’ve attempted to convert them to the local time for each city. However, I’m not sure if my conversion is accurate.

For example, the API gives me the sunrise in Toronto as 2:00 AM and sunset as 11:00 AM. However, according to Google (for today), the sunrise in Toronto should be 7:26 AM, and the sunset should be 4:44 PM.

Here is my code snippet

var timezoneOffset = weatherData.timezone; // Offset in seconds
var sunriseDate = new Date((weatherData.sys.sunrise + timezoneOffset) * 1000)
            .toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
var sunsetDate = new Date((weatherData.sys.sunset + timezoneOffset) * 1000)
            .toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });

console.log(sunriseDate);
console.log(sunsetDate);

I want to be sure that this code is giving the right output.

Here is the Json output for Toronto

{
  "coord": {
    "lon": -79.4163,
    "lat": 43.7001
  },
  "weather": [
    {
      "id": 803,
      "main": "Clouds",
      "description": "broken clouds",
      "icon": "04n"
    }
  ],
  "base": "stations",
  "main": {
    "temp": -0.86,
    "feels_like": -7.86,
    "temp_min": -1.56,
    "temp_max": -0.34,
    "pressure": 1011,
    "humidity": 72,
    "sea_level": 1011,
    "grnd_level": 994
  },
  "visibility": 10000,
  "wind": {
    "speed": 12.07,
    "deg": 250,
    "gust": 14.31
  },
  "clouds": {
    "all": 75
  },
  "dt": 1732929417,
  "sys": {
    "type": 2,
    "id": 2099289,
    "country": "CA",
    "sunrise": 1732883394,
    "sunset": 1732916569
  },
  "timezone": -18000,
  "id": 6167865,
  "name": "Toronto",
  "cod": 200
}

Solution

  • Some working code to compare with the post:

    var weatherData = {
      "coord": {
        "lon": -79.4163,
        "lat": 43.7001
      },
      "weather": [
        {
          "id": 803,
          "main": "Clouds",
          "description": "broken clouds",
          "icon": "04n"
        }
      ],
      "base": "stations",
      "main": {
        "temp": -0.86,
        "feels_like": -7.86,
        "temp_min": -1.56,
        "temp_max": -0.34,
        "pressure": 1011,
        "humidity": 72,
        "sea_level": 1011,
        "grnd_level": 994
      },
      "visibility": 10000,
      "wind": {
        "speed": 12.07,
        "deg": 250,
        "gust": 14.31
      },
      "clouds": {
        "all": 75
      },
      "dt": 1732929417,
      "sys": {
        "type": 2,
        "id": 2099289,
        "country": "CA",
        "sunrise": 1732883394,
        "sunset": 1732916569
      },
      "timezone": -18000,
      "id": 6167865,
      "name": "Toronto",
      "cod": 200
    };
    
    // sunrise and sunset from UTC seconds
    
    const sunrise = new Date((weatherData.sys.sunrise) * 1000);
    const sunset =  new Date((weatherData.sys.sunset) * 1000);
    
    function UTC_offset(seconds) {
      const sign = seconds < 0 ? '-' : '+';
      seconds = Math.abs(seconds);
      let hours = Math.floor( seconds/3600);
      seconds -= hours * 3600;
      let mins = Math.floor( seconds/60);
      return sign+hours.toString().padStart(2, '0')+mins.toString().padStart(2, '0');
    }
    
    function options( weatherData) {
      return {
        hour: '2-digit',
        minute: '2-digit',
        timeZone: UTC_offset( weatherData.timezone)
      }
    }
    
    console.log( "%s Sunrise: %s",
      weatherData.name,
      sunrise.toLocaleTimeString( [], options(weatherData))
    );
    console.log( "%s Sunset:  %s",
      weatherData.name,
      sunset.toLocaleTimeString( [], options(weatherData))
    );

    1. Decide what timezone the sunrise and sunset are to be reported in. The timezone of the geolocation used to obtain data from the API is a good choice and used above.

    2. Specify the actual timezone chosen for reporting as the timeZone property of the options object passed as the second argument to toLocaleTimeSting.

    3. Write an obscure and messy conversion from a timezone offset documented as being in seconds to a "±hhmm" offset string mentioned in the timeZone link in 2. above.

    4. Combine the code you've written with the API documentation to get the right results. E.G. apply the timezone offset to the output produced by toLocaleString, not to date calculations.

    Discussion

    There is something amiss with the reported output in the post. The working code above is based on posted code and at no stage ever changed the minutes of sunrise and sunset time to minutes that were not the same or 30 minutes different from times reported by the API.

    Two points to consider

    • Living in a timezone that is 9:30 hours east of GMT would easily account for a difference of 30 minute values if sunset/sunrise times were reported in local time on my PC.

    • If you continue to get minute values set to zero that do not correspond to times from the API then there is a problem in code that is not in the post.