如何从天气 API 数组中获取单独的每日数组,该数组每 3 小时提供 5 天的报告
How to get seperate daily array from the weather API array which gives a 5 days every 3 hours report
请检查您是否可以帮助任何人。我一直在开发我的天气应用程序,我正在使用带有 openweathermap.org 的 axios 在 React 上构建它
而且我有点坚持以我需要的方式获取数据。我正在使用它的 5 天预报。它为您提供一份报告,每 3 小时预测 5 days.It,为您提供 5 天的 40 份报告。因此,您会在中间的 3 天以及当前和第五天获得 8 份报告,您会根据当天剩余的时间获得剩余的报告。这是报告的 API 响应:report。
所以你会得到这个作为响应:
{
"data": {
"cod": "200",
"message": 0.0062,
"cnt": 39,
"list": [
{
"dt": 1540177200,
"main": {
"temp": 24.55,
"temp_min": 20.88,
"temp_max": 24.55,
"pressure": 1008.67,
"sea_level": 1025.96,
"grnd_level": 1008.67,
"humidity": 58,
"temp_kf": 3.67
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "02d"
}
],
"clouds": {
"all": 8
},
"wind": {
"speed": 3.82,
"deg": 340.5
},
"sys": {
"pod": "d"
},
"dt_txt": "2018-10-22 03:00:00"
},
{
"dt": 1540188000,
"main": {
...
},
},
{
"dt": 1540198800,
"main": {
...
},
},
{
"dt": 1540587600,
"main": {
. . .
}
}
]
}
我只是总结了 it.I 只输入了第一项的全部数据,其余的我输入了……它是一个包含 40 项的长数组。每个都有一个独特的日期时间戳,它的开头是“dt”。我需要根据特定日期获取 5 个数组。为此,我想到了转换时间戳(dt),然后获取导致相同“日”的所有项目。像这样转换时间戳(对所有项目使用 forEach):
let day ='';
day = new Date(dt *1000);
day = day.getDate();
转换数组时出现两个问题:
- 我又得到了一个包含 40 个项目的大数组,但我需要 5 个基于日期的数组,这样我就有了单独的每一天的报告
- 其次,我松开了时间戳中的 dt。我需要保留它,以便我可以在我的应用程序中显示天气预报。
我想根据该时间戳分别显示 5 天的信息。
感谢大家的帮助和想法。
//尝试使用 dt_text 格式化代码,然后使用下面的代码
//我试过你的代码,它让我感到不确定
console.log(formatDate("2014-07-23 09:00:00"));
function formatDate(date) {
let d = new Date(date),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = '' + d.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
return formattedDate = year + month + day;
}
您可以通过首先创建一个对象来保存从当前日期到未来 5 天的每一天的报告。然后遍历 "list"
的元素并将每个(报告)放在对象中的正确位置。
这是一个例子:
请注意,此代码中的 response
等于您在问题中包含的数据。
const today = new Date();
const day = 60 * 60 * 24 * 1000;
const dateBins = {};
const nBins = 6; // there can be reports for up to 6 distinct dates
for (let i = 0; i < nBins; i++) {
// set up a bin (empty array) for each date
const date = new Date(today.getTime() + i * day);
dateBins[date.getDate()] = [];
}
const reports = response.data.list;
for (const report of reports) {
const reportDate = new Date(report.dt * 1000).getDate();
dateBins[reportDate].push(report);
}
将 today
的声明更改为 new Date('2018-10-21T00:00:00.000Z')
将允许此代码使用您发布的特定数据。
使用您发布的数据 dateBins
的结果:
{ '21':
[ { dt: 1540177200,
main: [Object],
weather: [Array],
clouds: [Object],
wind: [Object],
sys: [Object],
dt_txt: '2018-10-22 03:00:00' },
{ dt: 1540188000, main: {} } ],
'22': [ { dt: 1540198800, main: {} } ],
'23': [],
'24': [],
'25': [],
'26': [ { dt: 1540587600, main: {} } ] }
我查看了很多选项,我的答案是 reduce 。我需要根据一个值重新组合我的响应,因为我有 5 天,所以我将有一个按天分组的数组,其中包含同一天的所有信息。我还需要保留我的时间戳,因为我需要该报告的一天中的时间。
// get the weather data and recreate an array
// having day and time(hour in my case) in the new array
const allData = [];
Object.entries(weatherInfo).forEach(([key, value]) => {
const dateTime = new Date(value.dt * 1000);
const day = dateTime.getDate();
const time = dateTime.getHours();
// recreate objects of the array adding time anda day and
// keeping timestamp and the rest of the info
const item = {
day: day,
time: time,
...value
};
allData.push(item);
return allData;
});
然后我有了一个新数组,我可以使用 reduce 感谢 并得到我正在寻找的结果:
// Now reduce it to an array grouped by day
const groupedByDay = "day";
const groupedArray = allData;
const groupBy = (groupedArray, groupedByDay) => {
return groupedArray.reduce((acc, obj) => {
const key = obj[groupedByDay];
!acc[key] ? (acc[key] = []) : acc[key].push(obj);
return acc;
}, {});
};
console.log(groupBy(groupedArray, groupedByDay));
我可以简单地删除顶部的那两个 const 定义并执行此操作:
const groupBy = (groupedArray, groupedByDay) => {
return groupedArray.reduce((acc, obj) => {
const key = obj[groupedByDay];
!acc[key] ? (acc[key] = []) : acc[key].push(obj);
return acc;
}, {});
};
console.log(groupBy(allData, 'day'));
//make a empty map for daily data
var dailyData={};
weatherData.list.map(item => {
const dateTime = new Date(item.dt * 1000);
const day = dateTime.getDate();
const time = dateTime.getHours();
// check if dailyData map has it
if(!dailyData[day] )
dailyData[day]=[];
dailyData[day].push({...item,day,time});
});
找到了一个复杂度为 0(n) 的更简单的解决方案。
我在下面找到了一个简单的方法
PS:Don不要跳过查看代码长度,我已经尝试在那里解释我的代码,这就是它看起来很长的原因!
const daysArray = [];
app.post("/", function (req, res) {
const cityName = req.body.cityName;
const url =
"https://api.openweathermap.org/data/2.5/forecast?q=" +
cityName +
"&appid={api_key}&units=metric";
https.get(url, function (response) {
response.on("data", function (data) {
const weatherData = JSON.parse(data);
***// The main part starts from below***
const time = new Date().getHours();
//1)We got hold of current time(24 hr - format)
weatherData.list.forEach(function (single) {
var textHour = single.dt_txt.substring(11, 13);
//2)We got hold of hour from weatherData
//example "dt_txt": "2020-07-28 21:00:00" ( var textHour= '21')
var numberHour = parseInt(textHour, 10);
//2) We converted string '21' to int 21 !
var difference = Math.abs(time - numberHour);
//3) In order to get latest time we finded out the difference
// i.e. The data from API comes strictly from 00:00 then 3 ,6 , ..,21,24 aka 00:00
// In order to get latest time we finded out the difference
//example if it was 22:00 the 22(time)-21(numberHour)=1(difference)
if (
difference === 1 ||
difference === 0 ||
(time === 23 && numberHour === 21) ||
(time === 24 && numberHour === 0) ||
(time === 2 && numberHour === 00)
)
//Here in first case
//If it was time=22 & numberHour=21 then difference=1
//Second Case if time=21 & numberHour=21 then difference =0
//Third Case if it was time=23 then 23-21=2 and the difference would be 2(Special Case)
//Fourth Case time=24 numberHour=0 , difference =24 (Special Case)
//Fifth Case time=2 numberHour=0:00 , difference = 2 (Special Case)
//NOW FOR ALL THE REST THE DIFFERENCE WOULD ONLY BE '0' AND '1'
{
daysArray.push(single);
//We pushed the satisfied timings in our daysArray
}
});
console.log(daysArray);
//BOOM , In console you will be seeing the 5-day data and that too closest to //your current time !
res.render("forecast", { daysArray: daysArray });
});
});
});
我是这个编程世界的新手,我的第一个帮手!
希望达标,欢迎指正:)
请检查您是否可以帮助任何人。我一直在开发我的天气应用程序,我正在使用带有 openweathermap.org 的 axios 在 React 上构建它 而且我有点坚持以我需要的方式获取数据。我正在使用它的 5 天预报。它为您提供一份报告,每 3 小时预测 5 days.It,为您提供 5 天的 40 份报告。因此,您会在中间的 3 天以及当前和第五天获得 8 份报告,您会根据当天剩余的时间获得剩余的报告。这是报告的 API 响应:report。 所以你会得到这个作为响应:
{
"data": {
"cod": "200",
"message": 0.0062,
"cnt": 39,
"list": [
{
"dt": 1540177200,
"main": {
"temp": 24.55,
"temp_min": 20.88,
"temp_max": 24.55,
"pressure": 1008.67,
"sea_level": 1025.96,
"grnd_level": 1008.67,
"humidity": 58,
"temp_kf": 3.67
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "02d"
}
],
"clouds": {
"all": 8
},
"wind": {
"speed": 3.82,
"deg": 340.5
},
"sys": {
"pod": "d"
},
"dt_txt": "2018-10-22 03:00:00"
},
{
"dt": 1540188000,
"main": {
...
},
},
{
"dt": 1540198800,
"main": {
...
},
},
{
"dt": 1540587600,
"main": {
. . .
}
}
]
}
我只是总结了 it.I 只输入了第一项的全部数据,其余的我输入了……它是一个包含 40 项的长数组。每个都有一个独特的日期时间戳,它的开头是“dt”。我需要根据特定日期获取 5 个数组。为此,我想到了转换时间戳(dt),然后获取导致相同“日”的所有项目。像这样转换时间戳(对所有项目使用 forEach):
let day ='';
day = new Date(dt *1000);
day = day.getDate();
转换数组时出现两个问题:
- 我又得到了一个包含 40 个项目的大数组,但我需要 5 个基于日期的数组,这样我就有了单独的每一天的报告
- 其次,我松开了时间戳中的 dt。我需要保留它,以便我可以在我的应用程序中显示天气预报。
我想根据该时间戳分别显示 5 天的信息。
感谢大家的帮助和想法。
//尝试使用 dt_text 格式化代码,然后使用下面的代码 //我试过你的代码,它让我感到不确定
console.log(formatDate("2014-07-23 09:00:00"));
function formatDate(date) {
let d = new Date(date),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = '' + d.getFullYear();
if (month.length < 2) month = '0' + month;
if (day.length < 2) day = '0' + day;
return formattedDate = year + month + day;
}
您可以通过首先创建一个对象来保存从当前日期到未来 5 天的每一天的报告。然后遍历 "list"
的元素并将每个(报告)放在对象中的正确位置。
这是一个例子:
请注意,此代码中的 response
等于您在问题中包含的数据。
const today = new Date();
const day = 60 * 60 * 24 * 1000;
const dateBins = {};
const nBins = 6; // there can be reports for up to 6 distinct dates
for (let i = 0; i < nBins; i++) {
// set up a bin (empty array) for each date
const date = new Date(today.getTime() + i * day);
dateBins[date.getDate()] = [];
}
const reports = response.data.list;
for (const report of reports) {
const reportDate = new Date(report.dt * 1000).getDate();
dateBins[reportDate].push(report);
}
将 today
的声明更改为 new Date('2018-10-21T00:00:00.000Z')
将允许此代码使用您发布的特定数据。
使用您发布的数据 dateBins
的结果:
{ '21':
[ { dt: 1540177200,
main: [Object],
weather: [Array],
clouds: [Object],
wind: [Object],
sys: [Object],
dt_txt: '2018-10-22 03:00:00' },
{ dt: 1540188000, main: {} } ],
'22': [ { dt: 1540198800, main: {} } ],
'23': [],
'24': [],
'25': [],
'26': [ { dt: 1540587600, main: {} } ] }
我查看了很多选项,我的答案是 reduce 。我需要根据一个值重新组合我的响应,因为我有 5 天,所以我将有一个按天分组的数组,其中包含同一天的所有信息。我还需要保留我的时间戳,因为我需要该报告的一天中的时间。
// get the weather data and recreate an array
// having day and time(hour in my case) in the new array
const allData = [];
Object.entries(weatherInfo).forEach(([key, value]) => {
const dateTime = new Date(value.dt * 1000);
const day = dateTime.getDate();
const time = dateTime.getHours();
// recreate objects of the array adding time anda day and
// keeping timestamp and the rest of the info
const item = {
day: day,
time: time,
...value
};
allData.push(item);
return allData;
});
然后我有了一个新数组,我可以使用 reduce 感谢
// Now reduce it to an array grouped by day
const groupedByDay = "day";
const groupedArray = allData;
const groupBy = (groupedArray, groupedByDay) => {
return groupedArray.reduce((acc, obj) => {
const key = obj[groupedByDay];
!acc[key] ? (acc[key] = []) : acc[key].push(obj);
return acc;
}, {});
};
console.log(groupBy(groupedArray, groupedByDay));
我可以简单地删除顶部的那两个 const 定义并执行此操作:
const groupBy = (groupedArray, groupedByDay) => {
return groupedArray.reduce((acc, obj) => {
const key = obj[groupedByDay];
!acc[key] ? (acc[key] = []) : acc[key].push(obj);
return acc;
}, {});
};
console.log(groupBy(allData, 'day'));
//make a empty map for daily data
var dailyData={};
weatherData.list.map(item => {
const dateTime = new Date(item.dt * 1000);
const day = dateTime.getDate();
const time = dateTime.getHours();
// check if dailyData map has it
if(!dailyData[day] )
dailyData[day]=[];
dailyData[day].push({...item,day,time});
});
找到了一个复杂度为 0(n) 的更简单的解决方案。
我在下面找到了一个简单的方法 PS:Don不要跳过查看代码长度,我已经尝试在那里解释我的代码,这就是它看起来很长的原因!
const daysArray = [];
app.post("/", function (req, res) {
const cityName = req.body.cityName;
const url =
"https://api.openweathermap.org/data/2.5/forecast?q=" +
cityName +
"&appid={api_key}&units=metric";
https.get(url, function (response) {
response.on("data", function (data) {
const weatherData = JSON.parse(data);
***// The main part starts from below***
const time = new Date().getHours();
//1)We got hold of current time(24 hr - format)
weatherData.list.forEach(function (single) {
var textHour = single.dt_txt.substring(11, 13);
//2)We got hold of hour from weatherData
//example "dt_txt": "2020-07-28 21:00:00" ( var textHour= '21')
var numberHour = parseInt(textHour, 10);
//2) We converted string '21' to int 21 !
var difference = Math.abs(time - numberHour);
//3) In order to get latest time we finded out the difference
// i.e. The data from API comes strictly from 00:00 then 3 ,6 , ..,21,24 aka 00:00
// In order to get latest time we finded out the difference
//example if it was 22:00 the 22(time)-21(numberHour)=1(difference)
if (
difference === 1 ||
difference === 0 ||
(time === 23 && numberHour === 21) ||
(time === 24 && numberHour === 0) ||
(time === 2 && numberHour === 00)
)
//Here in first case
//If it was time=22 & numberHour=21 then difference=1
//Second Case if time=21 & numberHour=21 then difference =0
//Third Case if it was time=23 then 23-21=2 and the difference would be 2(Special Case)
//Fourth Case time=24 numberHour=0 , difference =24 (Special Case)
//Fifth Case time=2 numberHour=0:00 , difference = 2 (Special Case)
//NOW FOR ALL THE REST THE DIFFERENCE WOULD ONLY BE '0' AND '1'
{
daysArray.push(single);
//We pushed the satisfied timings in our daysArray
}
});
console.log(daysArray);
//BOOM , In console you will be seeing the 5-day data and that too closest to //your current time !
res.render("forecast", { daysArray: daysArray });
});
});
});
我是这个编程世界的新手,我的第一个帮手! 希望达标,欢迎指正:)