getHistoricalWeather method
Fetch historical weather data for a specific date range.
Returns HourlyWeatherData with hourly data between startDate and
endDate. Available from 1940 onwards. Maximum range is 1 year.
Important: ERA5 archive data has a delay of about 5-7 days. The end date must be at least 7 days before today.
Implementation
Future<HourlyWeatherData> getHistoricalWeather({
required double latitude,
required double longitude,
required DateTime startDate,
required DateTime endDate,
}) async {
// ERA5 data has approximately 5-7 days delay.
final now = DateTime.now();
final maxEndDate = now.subtract(const Duration(days: 7));
// Validate date range.
if (endDate.isBefore(startDate)) {
throw ArgumentError('endDate must be after startDate');
}
if (endDate.isAfter(maxEndDate)) {
throw ArgumentError(
'ERA5 archive data has a 5-7 day delay. '
'End date must be at least 7 days before today. '
'Latest available date: ${maxEndDate.year}-${maxEndDate.month.toString().padLeft(2, '0')}-${maxEndDate.day.toString().padLeft(2, '0')}',
);
}
final daysDiff = endDate.difference(startDate).inDays;
if (daysDiff > 365) {
throw ArgumentError('Date range cannot exceed 365 days');
}
if (startDate.year < 1940) {
throw ArgumentError('Historical data only available from 1940 onwards');
}
final startDateStr =
'${startDate.year}-${startDate.month.toString().padLeft(2, '0')}-${startDate.day.toString().padLeft(2, '0')}';
final endDateStr =
'${endDate.year}-${endDate.month.toString().padLeft(2, '0')}-${endDate.day.toString().padLeft(2, '0')}';
final uri = Uri.parse(_archiveUrl).replace(
queryParameters: {
'latitude': latitude.toString(),
'longitude': longitude.toString(),
'start_date': startDateStr,
'end_date': endDateStr,
'hourly': [
'temperature_2m',
'relative_humidity_2m',
'wind_speed_10m',
'precipitation',
].join(','),
'timezone': 'Australia/Sydney',
},
);
try {
final response = await http.get(uri);
if (response.statusCode == 200) {
final json = jsonDecode(response.body) as Map<String, dynamic>;
return HourlyWeatherData.fromJson(json);
} else {
throw Exception(
'Failed to load historical weather data: ${response.statusCode}',
);
}
} catch (e) {
throw Exception('Failed to fetch historical weather: $e');
}
}