Я бы предложил использовать ответ-обещание-нативный, чтобы разрешить использование async / await. Это позволит нам перебирать список городов и прикреплять данные о погоде для каждого города к деталям города (название и страна).
Как только мы получим эти данные, мы сможем выполнить обработку, о которой вы упомянули, мы можем получить максимальную и минимальную температуры (обратите внимание, что температуры приведены в градусах Кельвина, поэтому мы переведем их в градусы Цельсия.)
Важно отметить, что я группируюсь по локальной дате , если вы хотите сгруппировать по utc date , вам следует изменить строку:
let timeOffset = entry.dt + result.weatherResponse.city.timezone;
до
let timeOffset = entry.dt;
Это немного другой способ интерпретации данных!
Я теперь обновил, чтобы сгруппировать по дате результаты выглядят так:
Группировка по локальной дате:
Date,Highest Temperature,Lowest Temperature,Cities With Rain
2019-11-01,Dubai,Oslo,"Paris,Berlin"
2019-11-02,Singapore,Oslo,"Lisbon,Paris,Berlin,Singapore"
2019-11-03,Singapore,Oslo,"Lisbon,Paris,Berlin,Athens,Singapore"
2019-11-04,Singapore,Oslo,"Lisbon,Paris,Berlin,Athens"
2019-11-05,Singapore,Oslo,"Lisbon,Paris,Berlin,Singapore"
2019-11-06,Singapore,Oslo,"Paris,Berlin,Singapore"
2019-11-07,Seoul,Seoul,""
Группировка по дате UTC:
Date,Highest Temperature,Lowest Temperature,Cities With Rain
2019-11-01,Dubai,Oslo,"Paris,Berlin"
2019-11-02,Singapore,Oslo,"Lisbon,Paris,Berlin,Singapore"
2019-11-03,Singapore,Oslo,"Lisbon,Paris,Berlin,Athens,Singapore"
2019-11-04,Singapore,Oslo,"Lisbon,Paris,Berlin,Athens"
2019-11-05,Singapore,Oslo,"Lisbon,Paris,Berlin,Singapore"
2019-11-06,Singapore,Oslo,"Paris,Berlin,Singapore"
Код:
const rp = require("request-promise-native");
const cities = {
0: ['Jerusalem', 'il'],
1: ['New York', 'us'],
2: ['Dubai', 'ae'],
3: ['Lisbon', 'pt'],
4: ['Oslo', 'no'],
5: ['Paris', 'fr'],
6: ['Berlin', 'de'],
7: ['Athens', 'gr'],
8: ['Seoul', 'kr'],
9: ['Singapore', 'sgp'],
}
async function getWeatherForCities() {
let results = [];
for (let [city, countryCode] of Object.values(cities)) {
console.log(`Getting weather for city: ${city}, country: ${countryCode}...`);
let weatherResponse = await rp({ url: `http://api.openweathermap.org/data/2.5/forecast?q=${city},${countryCode}&mode=json&appid=${apiKey}`, json: true});
results.push ({ city, countryCode, list: weatherResponse.list, weatherResponse });
}
let summary = results.map(res => {
return { city: res.city, countryCode: res.countryCode,
maxTemperature: getMaxTemperatureCelsius(res.list),
minTemperature: getMinTemperatureCelsius(res.list),
totalRainfall: getTotalRainFall(res.list)
}});
console.log("Summary (over forecasting interval): ", summary);
console.log("Result with the highest temperature: ", [...summary].sort((resA, resB) => resB.maxTemperature - resA.maxTemperature)[0]);
console.log("Result with the lowest temperature: ", [...summary].sort((resA, resB) => resA.minTemperature - resB.minTemperature)[0]);
console.log("Cities with rain: ", summary.filter(res => res.totalRainfall).map(res => res.city));
// Group by date (local) and city
let resultsGroupedByDateAndCity = {};
results.forEach(result => {
result.list.forEach(entry => {
let timeOffset = entry.dt + result.weatherResponse.city.timezone;
let date = new Date(timeOffset * 1000);
date.setHours(0,0,0,0);
let dateKey = date.toISOString().substring(0,10);
if (!resultsGroupedByDateAndCity[dateKey]) resultsGroupedByDateAndCity[dateKey] = {};
if (!resultsGroupedByDateAndCity[dateKey][result.city]) resultsGroupedByDateAndCity[dateKey][result.city] = [];
resultsGroupedByDateAndCity[dateKey][result.city].push(entry);
});
});
// Run through the keys.
let csvLines = ["Date,Highest Temperature,Lowest Temperature,Cities With Rain"];
for (let [date, obj] of Object.entries(resultsGroupedByDateAndCity)) {
let dailySummary = Object.entries(obj).map(([city, dayList]) => {
return { city,
maxTemperature: getMaxTemperatureCelsius(dayList),
minTemperature: getMinTemperatureCelsius(dayList),
totalRainfall: getTotalRainFall(dayList)
}});
console.log("Details for date " + date + ": ");
let resultWithHighestTemperature = [...dailySummary].sort((resA, resB) => resB.maxTemperature - resA.maxTemperature)[0];
let resultWithLowestTemperature = [...dailySummary].sort((resA, resB) => resA.minTemperature - resB.minTemperature)[0];
let citiesWithRain = dailySummary.filter(res => res.totalRainfall).map(res => res.city);
console.log("Result with the highest temperature: ", resultWithHighestTemperature);
console.log("Result with the lowest temperature: ", resultWithLowestTemperature);
console.log("Cities with rain: ", citiesWithRain);
csvLines.push([date, resultWithHighestTemperature.city, resultWithLowestTemperature.city, '"' + citiesWithRain.join(",") + '"'].join(","));
}
console.log("CSV result:\n", csvLines.join("\n"));
}
function KelvinToCelsius(kelvin) {
return (kelvin - 273.15);
}
// Return the max temperature for the forecast
function getMaxTemperatureCelsius(responseList) {
// Get a list of the max temperatures for the forecast.
const maxTemps = responseList.map(entry => Number(entry.main.temp_max));
return KelvinToCelsius(Math.max(...maxTemps));
}
// Return the min temperature for the forecast
function getMinTemperatureCelsius(responseList) {
// Get a list of the min temperatures for the forecast.
const minTemps = responseList.map(entry => Number(entry.main.temp_min));
return KelvinToCelsius(Math.min(...minTemps));
}
// Return the total rainfall for the forecast
function getTotalRainFall(responseList) {
// Get a list of the min temperatures for the forecast.
const rain = responseList.map(entry => { return entry.rain ? Number(entry.rain["3h"]): 0 });
return rain.reduce((sum, val) => sum + val, 0)
}
getWeatherForCities();