1

I've been able to pull temperatures of a specific city using the WorldTimeAPI:

jQuery.getJSON("https://api.openweathermap.org/data/2.5/weather?q=Rome&units=metric&appid=ab85ba57bbbb423fb62bfb8201126ede", function(data) {
console.log(data);
var temp = Math.floor(data.main.temp);
jQuery(".temp").append(temp  + '°C');
});

Now I'm trying to retrieve the date/time in a specific format (14 APR | 14:37)

jQuery.getJSON("http://worldtimeapi.org/api/timezone/Europe/Italy/Rome", function showDateTime() {
  var myDiv = document.getElementById("date-time");

  var date = new Date();
 // var dayList = ["DOM", "LUN", "MAR", "MER", "GIO", "VEN", "SAB"];
  var monthNames = [
    "GEN",
    "FEB",
    "MAR",
    "APR",
    "MAG",
    "GIU",
    "LUG",
    "AGO",
    "SET",
    "OTT",
    "NOV",
    "DEC"
  ];
  var dayName = dayList[date.getDay()];
//  var monthName = monthNames[date.getMonth()];
  var today = `${date.getDate()} ${monthName}`;

  var hour = date.getHours();
  var min = date.getMinutes();

  var time = hour + ":" + min;
  myDiv.innerText = `${today} | ${time}`;
}
setInterval(showDateTime, 0);

It pulls the time, and it's in real time, but of my local hour, and not of Rome (location I need to point to, and that I am successfully getting via the API for the temperature.

How can I get the time/date of Rome while connecting from somewhere else? I need to always show the current time/date of Rome and not of the user visiting.

Very appreciated!

  • Does this answer your question? [Javascript Date Parse with specific locale](https://stackoverflow.com/questions/50781887/javascript-date-parse-with-specific-locale) – Gerard Brull Apr 14 '22 at 13:43
  • You're getting data for Rome, USA, not Rome, Italy. Include the country in the API call `q=Rome,It` and you'll get the data you seek. – RobG Apr 15 '22 at 00:20

2 Answers2

0

The key to making it work is JS's toLocaleString() and related functions. Many (many!) formatting options can be found here.

The OP seemed to have the wrong url for the world time API (Europe/Italy/Rome), but the one used in the snippet (Europe/Rome) produces a reasonable response:

let timer;
let baseTime;

getRomeTime().then(result => baseTime = result);

document.getElementById('start').onclick = () => {
  updateTime(0); // edit: start right away
  timer = setInterval(updateTime(1000), 1000);
};

document.getElementById('stop').onclick = () => {
  clearInterval(timer);
};

function getRomeTime() {
  const url = "http://worldtimeapi.org/api/timezone/Europe/Rome"
  fetch(url)
    .then(r => r.json())
    .then(r => {
      return new Date(r.datetime);
    });
}

// add offset ms to the baseTime and update the DOM
function updateTime(offset) {
  baseTime = new Date(baseTime.getTime() + offset);

  const localeOptions = {
    timeZone: 'Europe/Rome',
    dateStyle: 'full',
    timeStyle: 'full'
  };
  const timetag = document.getElementById('timetag');
  timetag.innerText = d.toLocaleString('it-IT', localeOptions)
}
<p>L'ora è: <span id="timetag"></span></p>
<button id="start">Start</button>
<button id="stop">Stop</button>

Another edit: The time provider might not be intended for frequent invocations. In that case, we can approximate the same result by calling once, then updating the time with the time elapsed as computed on the client.

The snippet below gets Roma time just once, then increments the time by a second every second.

let timer;
let romeTime;

window.onload = () => {
  getRomeTime().then(result => {
    romeTime = result;
    updateTime(0)
    timer = setInterval(() => updateTime(1000), 1000);
  });
};

function getRomeTime() {
  const url = "http://worldtimeapi.org/api/timezone/Europe/Rome"
  return fetch(url)
    .then(r => r.json())
    .then(r => {
      return new Date(r.datetime);
    });
}

// add offset ms to the baseTime and update the DOM
function updateTime(offset) {
  romeTime = new Date(romeTime.getTime() + offset);

  const localeOptions = {
    timeZone: 'Europe/Rome',
    dateStyle: 'full',
    timeStyle: 'full'
  };
  const timetag = document.getElementById('timetag');
  timetag.innerText = romeTime.toLocaleString('it-IT', localeOptions)
}
<p>L'ora è: <span id="timetag"></span></p>
danh
  • 62,181
  • 10
  • 95
  • 136
  • *Date.prototype.toLocaleString* has supported ECMA-402 since edition 6 in June 2015. Hardly "relatively new". – RobG Apr 14 '22 at 15:48
  • @RobG, it depends on your unit of time. Choices are: years, decades, IE fixes. – danh Apr 14 '22 at 17:08
  • @danh, thanks a lot, this seems working quite well - just need to find a way to have it displayed in a HTML tag but even more important..is there a way to re-fetch the script every X seconds, so to get a real-time effect with the time? – Mirco Fragomena Apr 14 '22 at 21:49
  • @MircoFragomena - updated to insert the result in the dom on a recurring timer – danh Apr 14 '22 at 22:21
  • The list of supported timezones is returned by `http://worldtimeapi.org/api/timezone`. It seems to be the same as the list of [IANA representative locations](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). – RobG Apr 15 '22 at 01:34
  • @danh thanks! when I try the code on JSFiddle nothing happens - am I missing some specific libraries? https://jsfiddle.net/c7nvt3ok/ also, last detail - is it possible to have the clock showing right away, without having to press start? I wouldnt need the buttons, just the clock onLoad (but tried with InnerHTML and onLoad but won't work either..) – Mirco Fragomena Apr 15 '22 at 09:42
  • Putting a catch clause on the api call (which is a good practice in general) reveals that calling the api from the Fiddle produces an error with an unhelpfully empty error object. Perhaps the service has excluded JS Fiddle as a source of requests. Regarding starting right away, just do call periodic function once before setInterval. I'll edit the answer again. – danh Apr 15 '22 at 14:37
  • @MircoFragomena - I made one last edit. It won't make JS Fiddle cooperate with the time api, but it does use of the time API more sparingly, getting the absolute value just once, then using the client clock to keep it up-to-date. – danh Apr 15 '22 at 14:58
  • @danh I figured the problem on JS Fiddle was the http not being https - with https it triggers the timezone correctly! still though would love to remove the buttons and have the date/time displayed onLoad, but with timetag.innerText = romeTime.toLocaleString('it-IT', localeOptions) nothing shows up..have you been able to get it displayed right at the page load? buttons aren't needed – Mirco Fragomena Apr 15 '22 at 15:17
  • @MircoFragomena - We've drifted somewhat beyond the scope of the original question, which had to do with locale formatting. I've edited the second snippet to demonstrate window.onload. – danh Apr 15 '22 at 16:09
  • @danh you're right, and im sorry, but i dont know why we got the buttons introduced either haha nevertheless i appreciate your help a lot, thanks! hope this will be useful to others as well – Mirco Fragomena Apr 15 '22 at 17:01
0

According to the documentation,

OpenWeather uses Unix time and the UTC/GMT time zone for all API calls, including current weather, forecast and historical weather data.

Conversion from "UNIX time" to ECMAScript date object has been answered here.

The query in the OP returns data for location:

"lon": -85.1647,
"lat":  34.257

whereas Rome, Italy is at

"lat": 41.9
"lon": 12.483 

So you're getting the wrong "Rome". You can change the query to include the country code q=Rome,IT and you'll get data for the expected Rome.

Using the oncall API and the above coordinates or the updated query on 14 April returns sunrise and sunset as:

"sunrise":1649910690,
"sunset":1649958530

which can be converted to local time in Rome (Italy) using:

let opts = {timeZone:'Europe/Rome', timeZoneName:'short', hour12:false};
let sunrise = new Date(1649910690 * 1000).toLocaleString('en-CA', opts)
let sunset = new Date(1649958530 * 1000).toLocaleString('en-CA', opts)

console.log(`Sunrise: ${sunrise}\n` +
            `Sunset : ${sunset}`);

If you want to format the date and time in some other format, there are many questions about formatting dates. In this case you might use something like the following:

// Format date as 14 APR | 14:37
function myFormat(loc, date = new Date()) {
  let {month, day, hour, minute} = new Intl.DateTimeFormat('en', {
    day: 'numeric',
    month: 'short',
    hour: 'numeric',
    minute: '2-digit',
    timeZone: loc,
    hour12: false
  }).formatToParts(date).reduce((acc, part) => {
    acc[part.type] = part.value;
    return acc;
  }, Object.create(null));
  return `${day} ${month.toUpperCase()} | ${hour}:${minute}`;
}

// Current local date
console.log(`Current local time: \n${myFormat()}`);
// Date in Rome, Italy for supplied UNIX time value
console.log(`Sunrise for Rome, Italy local time:\n` +
  `${myFormat('Europe/Rome', new Date(1649910690 * 1000))}`
);
RobG
  • 142,382
  • 31
  • 172
  • 209
  • thanks this is quite nice with the format as i want! but i don't see the right time of Rome? it gets my local time, but the other time is not Rome..not sure if its the UNIX calc? – Mirco Fragomena Apr 14 '22 at 21:52
  • @MircoFragomena—the second time in the second example, "14 APR | 06:31" is from the value for sunrise returned from the API, "1649910690". It matches "Sunrise: 2022-04-14, 06:31:30 GMT+2" in the first example and is the local time for sunrise in Rome, Italy. – RobG Apr 14 '22 at 23:29
  • thanks, I got it now - but I'd need the local time of Rome, independently from where I login the website..not the sunrise?! I'll see if I can tweak your code though, thanks :) – Mirco Fragomena Apr 15 '22 at 09:34
  • That's exactly what the above does. All the times in the API are UTC, the above shows how to present them as local to the host or to anywhere in the world based on IANA representative location (e.g. Europe/Rome, Asia/Kolkata, etc.). – RobG Apr 16 '22 at 00:35