Skip to content

Commit c7b5b6e

Browse files
committed
feat: Historical api
1 parent 411368b commit c7b5b6e

2 files changed

Lines changed: 240 additions & 0 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package com.openmeteo.api
2+
3+
import com.openmeteo.api.common.Options
4+
import com.openmeteo.api.common.http.Endpoint
5+
import com.openmeteo.api.common.time.Date
6+
import com.openmeteo.api.common.time.Timezone
7+
import com.openmeteo.api.common.units.PrecipitationUnit
8+
import com.openmeteo.api.common.units.TemperatureUnit
9+
import com.openmeteo.api.common.units.Unit
10+
import com.openmeteo.api.common.units.WindSpeedUnit
11+
import kotlinx.serialization.SerialName
12+
import kotlinx.serialization.Serializable
13+
import java.net.URL
14+
import com.openmeteo.api.common.Response as R
15+
import com.openmeteo.api.common.query.Query as Q
16+
17+
object Historical : Endpoint(
18+
URL("https://archive-api.open-meteo.com/v1/archive")
19+
) {
20+
21+
operator fun invoke(query: Query) = query<Response, Query>(query)
22+
23+
@Serializable
24+
open class Query(
25+
override val latitude: Float,
26+
override val longitude: Float,
27+
override val daily: String? = null,
28+
override val hourly: String? = null,
29+
@SerialName("start_date")
30+
override val startDate: Date? = null,
31+
@SerialName("end_date")
32+
override val endDate: Date? = null,
33+
override val timezone: Timezone? = null,
34+
@SerialName("temperature_unit")
35+
override val temperatureUnit: TemperatureUnit? = null,
36+
@SerialName("windspeed_unit")
37+
override val windSpeedUnit: WindSpeedUnit? = null,
38+
@SerialName("precipitation_unit")
39+
override val precipitationUnit: PrecipitationUnit? = null,
40+
override val elevation: Float? = null,
41+
override val models: String? = null,
42+
) : Q.Coordinate, Q.Elevation, Q.DateRange, Q.Daily, Q.Hourly, Q.TimeFormat, Q.Timezone,
43+
Q.TemperatureUnit, Q.WindSpeedUnit, Q.PrecipitationUnit, Q.Models
44+
45+
@Serializable
46+
data class Response(
47+
override val latitude: Float,
48+
override val longitude: Float,
49+
override val utcOffsetSeconds: Int,
50+
override val timezone: Timezone,
51+
override val timezoneAbbreviation: String,
52+
override val generationtimeMs: Float,
53+
override val elevation: Float,
54+
override val dailyUnits: Map<String, Unit> = mapOf(),
55+
@SerialName("daily")
56+
override val dailyValues: Map<String, Array<Double?>> = mapOf(),
57+
override val hourlyUnits: Map<String, Unit> = mapOf(),
58+
@SerialName("hourly")
59+
override val hourlyValues: Map<String, Array<Double?>> = mapOf(),
60+
override val currentWeather: R.CurrentWeather.CurrentWeather? = null,
61+
) : R.Coordinate, R.Elevation, R.GenerationTimed, R.TimeZone, R.Daily, R.Hourly, R.CurrentWeather
62+
63+
@Serializable
64+
object Models : Options.Models {
65+
const val bestMatch="best_match"
66+
const val era5="era5"
67+
const val era5Land="era5_land"
68+
const val cerra="cerra"
69+
const val ecmwfIfs="ecmwf_ifs"
70+
}
71+
72+
@Serializable
73+
object Daily : Options.Daily {
74+
const val weathercode="weathercode"
75+
const val temperature2mMax="temperature_2m_max"
76+
const val temperature2mMin="temperature_2m_min"
77+
const val temperature2mMean="temperature_2m_mean"
78+
const val apparentTemperatureMax="apparent_temperature_max"
79+
const val apparentTemperatureMin="apparent_temperature_min"
80+
const val apparentTemperatureMean="apparent_temperature_mean"
81+
const val sunrise="sunrise"
82+
const val sunset="sunset"
83+
const val shortwaveRadiationSum="shortwave_radiation_sum"
84+
const val precipitationSum="precipitation_sum"
85+
const val rainSum="rain_sum"
86+
const val snowfallSum="snowfall_sum"
87+
const val precipitationHours="precipitation_hours"
88+
const val windspeed10mMax="windspeed_10m_max"
89+
const val windgusts10mMax="windgusts_10m_max"
90+
const val winddirection10mDominant="winddirection_10m_dominant"
91+
const val et0FaoEvapotranspiration="et0_fao_evapotranspiration"
92+
const val soilTemperature0To100cmMean="soil_temperature_0_to_100cm_mean"
93+
const val soilMoisture0To100cmMean="soil_moisture_0_to_100cm_mean"
94+
const val soilMoistureIndex0To100cmMean="soil_moisture_index_0_to_100cm_mean"
95+
const val growingDegreeDaysBase0Limit50="growing_degree_days_base_0_limit_50"
96+
const val leafWetnessProbabilityMean="leaf_wetness_probability_mean"
97+
const val vaporPressureDeficitMax="vapor_pressure_deficit_max"
98+
}
99+
100+
@Serializable
101+
object Hourly : Options.Hourly {
102+
const val temperature2m="temperature_2m"
103+
const val relativehumidity2m="relativehumidity_2m"
104+
const val dewpoint2m="dewpoint_2m"
105+
const val apparentTemperature="apparent_temperature"
106+
const val pressureMsl="pressure_msl"
107+
const val surfacePressure="surface_pressure"
108+
const val precipitation="precipitation"
109+
const val rain="rain"
110+
const val snowfall="snowfall"
111+
const val weathercode="weathercode"
112+
const val cloudcover="cloudcover"
113+
const val cloudcoverLow="cloudcover_low"
114+
const val cloudcoverMid="cloudcover_mid"
115+
const val cloudcoverHigh="cloudcover_high"
116+
const val shortwaveRadiation="shortwave_radiation"
117+
const val directRadiation="direct_radiation"
118+
const val diffuseRadiation="diffuse_radiation"
119+
const val directNormalIrradiance="direct_normal_irradiance"
120+
const val windspeed10m="windspeed_10m"
121+
const val windspeed100m="windspeed_100m"
122+
const val winddirection10m="winddirection_10m"
123+
const val winddirection100m="winddirection_100m"
124+
const val windgusts10m="windgusts_10m"
125+
const val et0FaoEvapotranspiration="et0_fao_evapotranspiration"
126+
const val vaporPressureDeficit="vapor_pressure_deficit"
127+
const val soilTemperature0To7cm="soil_temperature_0_to_7cm"
128+
const val soilTemperature7To28cm="soil_temperature_7_to_28cm"
129+
const val soilTemperature28To100cm="soil_temperature_28_to_100cm"
130+
const val soilTemperature100To255cm="soil_temperature_100_to_255cm"
131+
const val soilTemperature0To100cm="soil_temperature_0_to_100cm"
132+
const val soilMoisture0To7cm="soil_moisture_0_to_7cm"
133+
const val soilMoisture7To28cm="soil_moisture_7_to_28cm"
134+
const val soilMoisture28To100cm="soil_moisture_28_to_100cm"
135+
const val soilMoisture100To255cm="soil_moisture_100_to_255cm"
136+
const val soilMoisture0To100cm="soil_moisture_0_to_100cm"
137+
const val soilMoistureIndex0To7cm="soil_moisture_index_0_to_7cm"
138+
const val soilMoistureIndex7To28cm="soil_moisture_index_7_to_28cm"
139+
const val soilMoistureIndex28To100cm="soil_moisture_index_28_to_100cm"
140+
const val soilMoistureIndex100To255cm="soil_moisture_index_100_to_255cm"
141+
const val soilMoistureIndex0To100cm="soil_moisture_index_0_to_100cm"
142+
}
143+
144+
145+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.openmeteo.api
2+
3+
import com.openmeteo.api.common.Options
4+
import com.openmeteo.api.common.query.City
5+
import com.openmeteo.api.common.time.Date
6+
import com.openmeteo.api.common.units.Unit
7+
import kotlin.test.Test
8+
import kotlin.test.assertContains
9+
import kotlin.test.assertContentEquals
10+
import kotlin.test.assertEquals
11+
12+
class HistoricalTest {
13+
14+
@Test
15+
fun `Amsterdam, 1st january 2000, no models`() {
16+
val query = Historical.Query(
17+
latitude = City.Amsterdam.latitude,
18+
longitude = City.Amsterdam.longitude,
19+
hourly = Options.list(Forecast.Hourly) { of(
20+
temperature2m
21+
) },
22+
startDate = Date("2020-01-01"),
23+
endDate = Date("2020-01-01"),
24+
)
25+
Historical(query)
26+
.getOrThrow().run {
27+
assertEquals(52.40001f, latitude)
28+
assertEquals(4.900009f, longitude)
29+
assertEquals(0, utcOffsetSeconds)
30+
assertEquals("GMT", timezone.id)
31+
assertEquals("GMT", timezoneAbbreviation)
32+
assertEquals(17f, elevation)
33+
assert(hourlyUnits == mapOf(
34+
"time" to Unit.UnixTime,
35+
"temperature_2m" to Unit.Celsius,
36+
)
37+
)
38+
assertContains(hourlyValues, "time")
39+
assertContentEquals(arrayOf(
40+
1577836800.0,
41+
1577840400.0,
42+
1577844000.0,
43+
1577847600.0,
44+
1577851200.0,
45+
1577854800.0,
46+
1577858400.0,
47+
1577862000.0,
48+
1577865600.0,
49+
1577869200.0,
50+
1577872800.0,
51+
1577876400.0,
52+
1577880000.0,
53+
1577883600.0,
54+
1577887200.0,
55+
1577890800.0,
56+
1577894400.0,
57+
1577898000.0,
58+
1577901600.0,
59+
1577905200.0,
60+
1577908800.0,
61+
1577912400.0,
62+
1577916000.0,
63+
1577919600.0
64+
), hourlyValues["time"])
65+
assertContains(hourlyValues, "temperature_2m")
66+
assertContentEquals(arrayOf(
67+
2.0,
68+
1.9,
69+
1.6,
70+
1.5,
71+
1.2,
72+
1.0,
73+
0.7,
74+
0.5,
75+
0.5,
76+
1.0,
77+
1.6,
78+
2.4,
79+
3.1,
80+
3.5,
81+
3.4,
82+
3.2,
83+
2.5,
84+
2.1,
85+
2.0,
86+
1.6,
87+
1.9,
88+
2.1,
89+
2.2,
90+
2.3,
91+
), hourlyValues["temperature_2m"])
92+
}
93+
}
94+
95+
}

0 commit comments

Comments
 (0)