From 1048ef0b9125f60a329d52860eec3f7b08823305 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Sat, 28 May 2016 17:49:14 +0200 Subject: [PATCH] Add parser for wetter.de --- .../rhynodge/webpages/weather/WindDirection.kt | 34 +- .../webpages/weather/wetterde/HourState.kt | 24 + .../webpages/weather/wetterde/WetterDeFilter.kt | 88 + .../webpages/weather/wetterde/WetterDeState.kt | 38 + .../weather/wetterde/WetterDeFilterTest.kt | 82 + .../webpages/weather/wetterde/WetterDeStateTest.kt | 57 + .../webpages/weather/wetterde/wetter.de.html | 4063 ++++++++++++++++++++ 7 files changed, 4377 insertions(+), 9 deletions(-) create mode 100644 src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/HourState.kt create mode 100644 src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeFilter.kt create mode 100644 src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeState.kt create mode 100644 src/test/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeFilterTest.kt create mode 100644 src/test/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeStateTest.kt create mode 100644 src/test/resources/net/pterodactylus/rhynodge/webpages/weather/wetterde/wetter.de.html diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/WindDirection.kt b/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/WindDirection.kt index ab8b030..a2b7a8b 100644 --- a/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/WindDirection.kt +++ b/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/WindDirection.kt @@ -9,26 +9,42 @@ enum class WindDirection(val arrow: String) { NONE("↺"), NORTH("↓"), + NORTHNORTHEAST("↓↙"), NORTHEAST("↙"), + EASTNORTHEAST("↙←"), EAST("←"), + EASTSOUTHEAST("←↖"), SOUTHEAST("↖"), + SOUTHSOUTHEAST("↖↑"), SOUTH("↑"), + SOUTHSOUTHWEST("↑↗"), SOUTHWEST("↗"), + WESTSOUTHWEST("↗→"), WEST("→"), - NORTHWEST("↘") + WESTNORTHWEST("→↘"), + NORTHWEST("↘"), + NORTHNORTHWEST("↘↓") } fun String.toWindDirection(): WindDirection { return when (this) { - "N" -> WindDirection.NORTH - "NO" -> WindDirection.NORTHEAST - "O" -> WindDirection.EAST - "SO" -> WindDirection.SOUTHEAST - "S" -> WindDirection.SOUTH - "SW" -> WindDirection.SOUTHWEST - "W" -> WindDirection.WEST - "NW" -> WindDirection.NORTHWEST + "N", "Nord" -> WindDirection.NORTH + "Nordnordost" -> WindDirection.NORTHNORTHEAST + "NO", "Nordost" -> WindDirection.NORTHEAST + "Ostnordost" -> WindDirection.EASTNORTHEAST + "O", "Ost" -> WindDirection.EAST + "Ostsüdost" -> WindDirection.EASTSOUTHEAST + "SO", "Südost" -> WindDirection.SOUTHEAST + "Südsüdost" -> WindDirection.SOUTHSOUTHEAST + "S", "Süd" -> WindDirection.SOUTH + "Südsüdwest" -> WindDirection.SOUTHSOUTHWEST + "SW", "Südwest" -> WindDirection.SOUTHWEST + "Westsüdwest" -> WindDirection.WESTSOUTHWEST + "W", "West" -> WindDirection.WEST + "Westnordwest" -> WindDirection.WESTNORTHWEST + "NW", "Nordwest" -> WindDirection.NORTHWEST + "Nordnordwest" -> WindDirection.NORTHNORTHWEST else -> WindDirection.NONE } } diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/HourState.kt b/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/HourState.kt new file mode 100644 index 0000000..f8e7dc6 --- /dev/null +++ b/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/HourState.kt @@ -0,0 +1,24 @@ +package net.pterodactylus.rhynodge.webpages.weather.wetterde + +import com.fasterxml.jackson.annotation.JsonProperty +import net.pterodactylus.rhynodge.webpages.weather.WindDirection + +/** + * Container for weather conditions of a single hour. + * + * @author [David ‘Bombe’ Roden](mailto:bombe@pterodactylus.net) + */ +data class HourState( + @JsonProperty("hourIndex") val hourIndex: Int, + @JsonProperty("temperature") val temperature: Int, + @JsonProperty("feltTemperature") val feltTemperature: Int, + @JsonProperty("rainProbability") val rainProbability: Double, + @JsonProperty("rainAmount") val rainAmount: Double, + @JsonProperty("windDirection") val windDirection: WindDirection, + @JsonProperty("windSpeed") val windSpeed: Int, + @JsonProperty("gustSpeed") val gustSpeed: Int, + @JsonProperty("humidity") val humidity: Double, + @JsonProperty("description") val description: String, + @JsonProperty("image") val image: String) { + +} diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeFilter.kt b/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeFilter.kt new file mode 100644 index 0000000..4e7010e --- /dev/null +++ b/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeFilter.kt @@ -0,0 +1,88 @@ +package net.pterodactylus.rhynodge.webpages.weather.wetterde + +import net.pterodactylus.rhynodge.Filter +import net.pterodactylus.rhynodge.State +import net.pterodactylus.rhynodge.states.FailedState +import net.pterodactylus.rhynodge.states.HtmlState +import net.pterodactylus.rhynodge.webpages.weather.WindDirection +import net.pterodactylus.rhynodge.webpages.weather.toWindDirection +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import java.time.DateTimeException +import java.time.LocalDate +import java.time.LocalTime +import java.time.ZoneId +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.util.Locale + +/** + * HTML parser for [wetter.de](https://www.wetter.de/). + * + * @author [David ‘Bombe’ Roden](mailto:bombe@pterodactylus.net) + */ +class WetterDeFilter : Filter { + + object DateParser { + val parser = DateTimeFormatter.ofPattern("dd. MMM yyyy").withLocale(Locale.GERMAN).withZone(ZoneId.of("Europe/Berlin")) + } + + override fun filter(state: State): State { + if (state.success().not()) { + return FailedState.from(state) + } + state as? HtmlState ?: throw IllegalArgumentException("state is not an HTML state") + + return parseWetterDeState(state) + } + + private fun parseWetterDeState(htmlState: HtmlState): WetterDeState { + val dateTime = parseDate(htmlState.document()) ?: throw IllegalArgumentException("date can not be parsed") + val wetterDeState = WetterDeState(dateTime) + parseHourStates(htmlState.document()).forEach { wetterDeState += it } + return wetterDeState + } + + private fun parseDate(document: Document): ZonedDateTime? { + return document.select(".forecast-detail-headline").text() + .extract(Regex(".*?([0-9]{1,2}\\. [^ ]+ [0-9]{4}).*?$"))?.toDate() ?: return null + } + + private fun String.extract(regex: Regex): String? { + return regex.find(this)?.groups?.get(1)?.value + } + + private fun String.toDate(): ZonedDateTime? { + return try { + ZonedDateTime.of(DateParser.parser.parse(this, LocalDate::from), LocalTime.of(0, 0), ZoneId.of("Europe/Berlin")) + } catch (e: DateTimeException) { + e.printStackTrace() + null + } + } + + private fun parseHourStates(document: Document): Collection { + return document.select(".forecast-detail-column-1h").mapIndexed { index, element -> parseHourState(index, element) } + } + + private fun parseHourState(index: Int, element: Element): HourState { + return HourState( + index, + element.select("span.temperature").text().extract(Regex("([0-9]+).*$"))?.toInt() ?: 0, + element.select("span.temperature-wind-chill").text().extract(Regex("[^0-9]*?([0-9]+)[^0-9]*?"))?.toInt() ?: 0, + (element.select(".forecast-icon-rain-fill").attr("style").extract(Regex("[^0-9]*?([0-9]+)[^0-9]*?"))?.toInt() ?: 0) / 100.0, + element.select(".forecast-rain span:eq(4)").text().replace(',', '.').extract(Regex("[^0-9]*?([0-9\\.]+)[^0-9]*?"))?.toDouble() ?: 0.0, + element.select(".forecast-wind-text").text().extract(Regex(".*?(Nord((nord)?(ost|west))?|Ost((nord|süd)ost)?|Süd((süd)?(ost|west))?|West((nord|süd)west)?).*?"))?.toWindDirection() ?: WindDirection.NONE, + element.select(".forecast-wind-text span:eq(1)").text().extract(Regex(".*?([0-9]+) km/h.*?"))?.toInt() ?: 0, + element.select(".forecast-wind-text span:eq(4)").text().extract(Regex(".*?([0-9]+) km/h.*?"))?.toInt() ?: 0, + (element.select(".forecast-humidity-text span:eq(0)").text().extract(Regex("([0-9]+)[^0-9]*?"))?.toInt() ?: 0) / 100.0, + element.select("span.temperature-condition").text(), + element.select(".forecast-image img").attr("src").prefixProtocol() + ) + } + + private fun String.prefixProtocol(): String { + return if (startsWith("//")) "http:" + this else this + } + +} diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeState.kt b/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeState.kt new file mode 100644 index 0000000..2651ed5 --- /dev/null +++ b/src/main/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeState.kt @@ -0,0 +1,38 @@ +package net.pterodactylus.rhynodge.webpages.weather.wetterde + +import com.fasterxml.jackson.annotation.JsonProperty +import net.pterodactylus.rhynodge.states.AbstractState +import java.time.Instant +import java.time.ZoneId.of +import java.time.ZonedDateTime + +/** + * Contains the state parsed from [wetter.de](https://www.wetter.de/). + * + * @author [David ‘Bombe’ Roden](mailto:bombe@pterodactylus.net) + */ +class WetterDeState(val dateTime: ZonedDateTime) : AbstractState(true), Iterable { + + constructor(@JsonProperty("dateTime") timeMillis: Long) : this(Instant.ofEpochMilli(timeMillis).atZone(of("Europe/Berlin"))) + + val hours: List = mutableListOf() + + val timeMillis: Long + @JsonProperty("dateTime") get() { + return dateTime.toInstant().toEpochMilli() + } + + override fun iterator(): Iterator = hours.iterator() + + operator fun plusAssign(hourState: HourState) { + (hours as MutableList).add(hourState) + } + + override fun equals(other: Any?): Boolean { + if (other !is WetterDeState) { + return false + } + return (dateTime == other.dateTime) and (hours == other.hours) + } + +} diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeFilterTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeFilterTest.kt new file mode 100644 index 0000000..3e7a25a --- /dev/null +++ b/src/test/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeFilterTest.kt @@ -0,0 +1,82 @@ +package net.pterodactylus.rhynodge.webpages.weather.wetterde + +import net.pterodactylus.rhynodge.filters.ResourceLoader +import net.pterodactylus.rhynodge.states.AbstractState +import net.pterodactylus.rhynodge.states.FailedState +import net.pterodactylus.rhynodge.states.HtmlState +import net.pterodactylus.rhynodge.webpages.weather.WindDirection +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.`is` +import org.hamcrest.Matchers.contains +import org.junit.Rule +import org.junit.Test +import org.junit.rules.ExpectedException +import java.time.ZoneId +import java.time.ZonedDateTime + +/** + * Unit test for [WetterDeFilter]. + + * @author [David ‘Bombe’ Roden](mailto:bombe@pterodactylus.net) + */ +class WetterDeFilterTest { + + @Rule @JvmField val expectedException = ExpectedException.none() + + private val url = "" + private val filter = WetterDeFilter() + + @Test + fun filterReturnsFailedStateIfGivenAFailedState() { + val previousState = FailedState.INSTANCE + assertThat(filter.filter(previousState).success(), `is`(false)) + } + + @Test + fun filterThrowsExceptionIfNotGivenAnHtmlState() { + val successfulHonHtmlState = object : AbstractState(true) {} + expectedException.expect(IllegalArgumentException::class.java) + filter.filter(successfulHonHtmlState) + } + + @Test + fun filterCanParseDateCorrectly() { + val htmlState = HtmlState(url, ResourceLoader.loadDocument(javaClass, "wetter.de.html", url)) + val wetterDeState = filter.filter(htmlState) as WetterDeState + assertThat(wetterDeState.dateTime, `is`(ZonedDateTime.of(2016, 5, 30, 0, 0, 0, 0, ZoneId.of("Europe/Berlin")))) + } + + @Test + fun filterParsesHoursCorrectly() { + val htmlState = HtmlState(url, ResourceLoader.loadDocument(javaClass, "wetter.de.html", url)) + val wetterDeState = filter.filter(htmlState) as WetterDeState + assertThat(wetterDeState, contains( + HourState(0, 18, 18, 0.47, 0.4, WindDirection.NORTHEAST, 19, 41, 0.91, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/017_M.png?o44shg"), + HourState(1, 18, 18, 0.60, 0.6, WindDirection.NORTHEAST, 20, 39, 0.91, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/017_M.png?o44shg"), + HourState(2, 18, 18, 0.59, 0.6, WindDirection.NORTHEAST, 20, 39, 0.89, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/017_M.png?o44shg"), + HourState(3, 18, 18, 0.49, 0.7, WindDirection.NORTHEAST, 19, 39, 0.89, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/017_M.png?o44shg"), + HourState(4, 18, 18, 0.38, 0.5, WindDirection.NORTHEAST, 19, 39, 0.89, "unbeständig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/022_M.png?o44shg"), + HourState(5, 17, 18, 0.35, 0.4, WindDirection.NORTHEAST, 19, 39, 0.90, "unbeständig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/010_M.png?o44shg"), + HourState(6, 17, 19, 0.45, 0.6, WindDirection.NORTHEAST, 19, 39, 0.91, "unbeständig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/010_M.png?o44shg"), + HourState(7, 18, 19, 0.59, 1.0, WindDirection.NORTHEAST, 19, 39, 0.88, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(8, 19, 20, 0.64, 0.7, WindDirection.EASTNORTHEAST, 19, 39, 0.83, "unbeständig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/010_M.png?o44shg"), + HourState(9, 20, 21, 0.59, 0.3, WindDirection.EASTNORTHEAST, 20, 41, 0.79, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(10, 21, 21, 0.50, 0.2, WindDirection.EASTNORTHEAST, 20, 43, 0.75, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(11, 22, 22, 0.39, 0.1, WindDirection.EASTNORTHEAST, 20, 44, 0.71, "wechselhaft", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/010_M.png?o44shg"), + HourState(12, 23, 23, 0.24, 0.05, WindDirection.EASTNORTHEAST, 20, 44, 0.70, "heiter", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/003_M.png?o44shg"), + HourState(13, 24, 24, 0.13, 0.02, WindDirection.EAST, 20, 46, 0.68, "heiter", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/003_M.png?o44shg"), + HourState(14, 24, 24, 0.11, 0.01, WindDirection.EAST, 20, 48, 0.66, "heiter", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/003_M.png?o44shg"), + HourState(15, 25, 23, 0.17, 0.2, WindDirection.EAST, 22, 48, 0.64, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(16, 24, 22, 0.23, 0.5, WindDirection.EAST, 22, 50, 0.65, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(17, 24, 22, 0.27, 0.7, WindDirection.EAST, 24, 50, 0.67, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(18, 24, 22, 0.34, 1.0, WindDirection.EASTNORTHEAST, 24, 48, 0.68, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(19, 23, 21, 0.45, 1.6, WindDirection.EASTNORTHEAST, 22, 48, 0.72, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(20, 22, 23, 0.50, 0.9, WindDirection.EASTNORTHEAST, 20, 44, 0.77, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(21, 21, 22, 0.44, 0.1, WindDirection.EASTNORTHEAST, 19, 41, 0.80, "gewittrig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/016_M.png?o44shg"), + HourState(22, 20, 20, 0.36, 0.09, WindDirection.EASTNORTHEAST, 17, 39, 0.84, "heiter bis wolkig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/004_M.png?o44shg"), + HourState(23, 19, 19, 0.31, 0.06, WindDirection.EASTNORTHEAST, 17, 35, 0.87, "heiter bis wolkig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/004_M.png?o44shg"), + HourState(24, 19, 20, 0.22, 0.03, WindDirection.EASTNORTHEAST, 15, 33, 0.89, "heiter bis wolkig", "http://cdn.static-fra.de/wetterv3/css/images/icons/weather/m/004_M.png?o44shg") + )) + } + +} diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeStateTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeStateTest.kt new file mode 100644 index 0000000..b3de810 --- /dev/null +++ b/src/test/kotlin/net/pterodactylus/rhynodge/webpages/weather/wetterde/WetterDeStateTest.kt @@ -0,0 +1,57 @@ +package net.pterodactylus.rhynodge.webpages.weather.wetterde + +import com.fasterxml.jackson.databind.ObjectMapper +import net.pterodactylus.rhynodge.webpages.weather.WindDirection +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.`is` +import org.junit.Test +import java.time.ZoneId.of +import java.time.ZonedDateTime + +/** + * Unit test for [WetterDeState]. + * + * @author [David ‘Bombe’ Roden](mailto:bombe@pterodactylus.net) + */ +class WetterDeStateTest { + + private val now = ZonedDateTime.now(of("Europe/Berlin")) + + @Test + fun statesWithTheSameDateAndHoursAreEqual() { + val firstState = WetterDeState(now) + firstState += createHourState(0) + firstState += createHourState(1) + val secondState = WetterDeState(now) + secondState += createHourState(0) + secondState += createHourState(1) + assertThat(firstState, `is`(secondState)) + } + + private fun createHourState(hourIndex: Int): HourState { + return HourState( + hourIndex, + 10 + hourIndex, + 12 + hourIndex, + (50 + hourIndex) / 100.0, + hourIndex.toDouble(), + WindDirection.values().get(hourIndex % WindDirection.values().size), + 20 + hourIndex, + 30 + hourIndex, + (40 + hourIndex) / 100.0, + "foo: " + hourIndex, + "//" + hourIndex + ) + } + + @Test + fun stateIsSerializableAsJson() { + val originalState = WetterDeState(now) + originalState += createHourState(0) + originalState += createHourState(1) + val json = ObjectMapper().writeValueAsString(originalState) + val parsedState = ObjectMapper().readValue(json, WetterDeState::class.java) + assertThat(parsedState, `is`(originalState)) + } + +} diff --git a/src/test/resources/net/pterodactylus/rhynodge/webpages/weather/wetterde/wetter.de.html b/src/test/resources/net/pterodactylus/rhynodge/webpages/weather/wetterde/wetter.de.html new file mode 100644 index 0000000..8fb8021 --- /dev/null +++ b/src/test/resources/net/pterodactylus/rhynodge/webpages/weather/wetterde/wetter.de.html @@ -0,0 +1,4063 @@ + + + + + + + + + + + + + + + +Wetterbericht für übermorgen in Hamburg, Deutschland - wetter.de + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ + +
+ + + +
+ +
+
+ + + + + + + + +
+
+ +
+
+
+ + + + + + + + +
+
+
+
+ +
+
+
+
+ +
+
+

Wetter übermorgen in Hamburg, Hamburg

+
+ +
+
+ +
+
+
+ +
+
+
+
+ +
+
+
    + + +
  • + Sa
    28.
    +
  • + + +
  • + So
    29.
    +
  • + + +
  • + Mo
    30.
    +
  • + + +
  • + Di
    31.
    +
  • + + +
  • + Mi
    01.
    +
  • + + +
  • + Do
    02.
    +
  • + + +
  • + Fr
    03.
    +
  • + + +
  • + Sa
    04.
    +
  • + + +
  • + So
    05.
    +
  • + + +
  • + Mo
    06.
    +
  • + + +
  • + Di
    07.
    +
  • + + +
  • + Mi
    08.
    +
  • + + +
  • + Do
    09.
    +
  • + + +
  • + Fr
    10.
    +
  • + + +
  • + Sa
    11.
    +
  • + +
+
+
+
+ +
+
Montag, den 30. Mai 2016
+
+ + +
+
Wettervorwarnung
+
+ Schwere Gewitter, teils mit Sturmböen, Starkregen, Hagel und/oder vielen Blitzen möglich. + (gültig vom 29.05.2016 15:00 Uhr - 31.05.2016 01:00 Uhr) +
+
+ +
+
+
gewittrig
+ +
+
+
25° / 17°
+
+
+
+ Es werden Höchsttemperaturen von 25° (gefühlt: 23°) und mäßiger Wind (24 km/h) aus Ost mit steifen Böen (50 km/h) erwartet. Es kommt zu Niederschlagsmengen von 5 - 15 l/m², die Niederschlagswahrscheinlichkeit beträgt 90%, die Sonne scheint 5 Stunden.
+ +
+ + + +
+
+
+
+
00:00
+ +
+
+
gewittrig
+
+ 18° + ( 18° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 47% + | 0,4 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (19 km/h / 3 Bft) + aus Nordost + + mit starken Böen (41 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 91 % + Luftdruck 1005,7 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
01:00
+ +
+
+
gewittrig
+
+ 18° + ( 18° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 60% + | 0,6 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (20 km/h / 4 Bft) + aus Nordost + + mit starken Böen (39 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 91 % + Luftdruck 1005,4 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
02:00
+ +
+
+
gewittrig
+
+ 18° + ( 18° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 59% + | 0,6 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (20 km/h / 4 Bft) + aus Nordost + + mit starken Böen (39 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 89 % + Luftdruck 1005 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
03:00
+ +
+
+
gewittrig
+
+ 18° + ( 18° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 49% + | 0,7 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (19 km/h / 3 Bft) + aus Nordost + + mit starken Böen (39 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 89 % + Luftdruck 1004,5 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
04:00
+ +
+
+
unbeständig
+
+ 18° + ( 18° ) + unbeständig +
+
+
+
+ +
+
+
+ Risiko 38% + | 0,5 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (19 km/h / 3 Bft) + aus Nordost + + mit starken Böen (39 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 89 % + Luftdruck 1003,9 hPa +
+
+
+
+
+ +
+ 04:59 Sonnenaufgang +
+ + + +
+ +
+
+
+ + +
+
+
+
+
05:00
+ +
+
+
unbeständig
+
+ 17° + ( 18° ) + unbeständig +
+
+
+
+ +
+
+
+ Risiko 35% + | 0,4 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (19 km/h / 3 Bft) + aus Nordost + + mit starken Böen (39 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 90 % + Luftdruck 1003,4 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + + +
+
+
+
+
06:00
+ +
+
+
unbeständig
+
+ 17° + ( 19° ) + unbeständig +
+
+
+
+ +
+
+
+ Risiko 45% + | 0,6 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (19 km/h / 3 Bft) + aus Nordost + + mit starken Böen (39 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 91 % + Luftdruck 1003,3 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
07:00
+ +
+
+
gewittrig
+
+ 18° + ( 19° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 59% + | 1 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (19 km/h / 3 Bft) + aus Nordost + + mit starken Böen (39 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 88 % + Luftdruck 1003,3 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
08:00
+ +
+
+
unbeständig
+
+ 19° + ( 20° ) + unbeständig +
+
+
+
+ +
+
+
+ Risiko 64% + | 0,7 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (19 km/h / 3 Bft) + aus Ostnordost + + mit starken Böen (39 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 83 % + Luftdruck 1003,3 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
09:00
+ +
+
+
gewittrig
+
+ 20° + ( 21° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 59% + | 0,3 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (20 km/h / 4 Bft) + aus Ostnordost + + mit starken Böen (41 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 79 % + Luftdruck 1003,1 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
10:00
+ +
+
+
gewittrig
+
+ 21° + ( 21° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 50% + | 0,2 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (20 km/h / 4 Bft) + aus Ostnordost + + mit starken Böen (43 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 75 % + Luftdruck 1002,9 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
11:00
+ +
+
+
wechselhaft
+
+ 22° + ( 22° ) + wechselhaft +
+
+
+
+ +
+
+
+ Risiko 39% + | 0,1 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (20 km/h / 4 Bft) + aus Ostnordost + + mit starken Böen (44 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 71 % + Luftdruck 1002,9 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
12:00
+ +
+
+
heiter
+
+ 23° + ( 23° ) + heiter +
+
+
+
+ +
+
+
+ Risiko 24% + | 0,05 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (20 km/h / 4 Bft) + aus Ostnordost + + mit starken Böen (44 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 70 % + Luftdruck 1003,1 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
13:00
+ +
+
+
heiter
+
+ 24° + ( 24° ) + heiter +
+
+
+
+ +
+
+
+ Risiko 13% + | 0,02 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (20 km/h / 4 Bft) + aus Ost + + mit starken Böen (46 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 68 % + Luftdruck 1003,5 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
14:00
+ +
+
+
heiter
+
+ 24° + ( 24° ) + heiter +
+
+
+
+ +
+
+
+ Risiko 11% + | 0,01 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (20 km/h / 4 Bft) + aus Ost + + mit starken Böen (48 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 66 % + Luftdruck 1003,9 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
15:00
+ +
+
+
gewittrig
+
+ 25° + ( 23° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 17% + | 0,2 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (22 km/h / 4 Bft) + aus Ost + + mit starken Böen (48 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 64 % + Luftdruck 1004,3 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
16:00
+ +
+
+
gewittrig
+
+ 24° + ( 22° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 23% + | 0,5 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (22 km/h / 4 Bft) + aus Ost + + mit steifen Böen (50 km/h / 7 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 65 % + Luftdruck 1004,6 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
17:00
+ +
+
+
gewittrig
+
+ 24° + ( 22° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 27% + | 0,7 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (24 km/h / 4 Bft) + aus Ost + + mit steifen Böen (50 km/h / 7 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 67 % + Luftdruck 1005 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ +
+
Abends
+
+ +
+
+
+
+
18:00
+ +
+
+
gewittrig
+
+ 24° + ( 22° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 34% + | 1 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (24 km/h / 4 Bft) + aus Ostnordost + + mit starken Böen (48 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 68 % + Luftdruck 1005,3 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
19:00
+ +
+
+
gewittrig
+
+ 23° + ( 21° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 45% + | 1,6 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (22 km/h / 4 Bft) + aus Ostnordost + + mit starken Böen (48 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 72 % + Luftdruck 1005,7 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
20:00
+ +
+
+
gewittrig
+
+ 22° + ( 23° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 50% + | 0,9 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (20 km/h / 4 Bft) + aus Ostnordost + + mit starken Böen (44 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 77 % + Luftdruck 1006,1 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
21:00
+ +
+
+
gewittrig
+
+ 21° + ( 22° ) + gewittrig +
+
+
+
+ +
+
+
+ Risiko 44% + | 0,1 l/m² +
+ +
+
+ +
+
+ mäßiger Wind (19 km/h / 3 Bft) + aus Ostnordost + + mit starken Böen (41 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 80 % + Luftdruck 1006,5 hPa +
+
+
+
+
+ + +
+ 21:36 Sonnenuntergang +
+ + +
+ +
+
+
+ + +
+
+
+
+
22:00
+ +
+
+
heiter bis wolkig
+
+ 20° + ( 20° ) + heiter bis wolkig +
+
+
+
+ +
+
+
+ Risiko 36% + | 0,09 l/m² +
+ +
+
+ +
+
+ schwacher Wind (17 km/h / 3 Bft) + aus Ostnordost + + mit starken Böen (39 km/h / 6 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 84 % + Luftdruck 1006,9 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
23:00
+ +
+
+
heiter bis wolkig
+
+ 19° + ( 19° ) + heiter bis wolkig +
+
+
+
+ +
+
+
+ Risiko 31% + | 0,06 l/m² +
+ +
+
+ +
+
+ schwacher Wind (17 km/h / 3 Bft) + aus Ostnordost + + mit frischen Böen (35 km/h / 5 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 87 % + Luftdruck 1007,4 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+ + +
+
+
+
+
24:00
+ +
+
+
heiter bis wolkig
+
+ 19° + ( 20° ) + heiter bis wolkig +
+
+
+
+ +
+
+
+ Risiko 22% + | 0,03 l/m² +
+ +
+
+ +
+
+ schwacher Wind (15 km/h / 3 Bft) + aus Ostnordost + + mit frischen Böen (33 km/h / 5 Bft) + +
+
+
+ +
+
+ +
+
+ Luftfeuchtigkeit 89 % + Luftdruck 1007,7 hPa +
+
+
+
+
+ + + + +
+ +
+
+
+
+
+ +
+
+
+ Pollenvorhersage gering +
+
+ Heute wird geringer Pollenflug erwartet:
+ Gräser +
+
+
+ +
+ +
+
Tagesdaten
+
+ +
+
+ Sonnenaufgang
+ 04:59 Uhr +
+ +
+ Sonnenuntergang
+ 21:36 Uhr +
+ +
+ Sonnenstunden
+ 05:00 h +
+ +
+ Niederschlag (gesamt)
+ 5 - 15 l/m² +
+ +
+ Luftfeuchtigkeit
+ 66% +
+ +
+
+
+ Mondaufgang
+ 02:25 Uhr +
+ +
+ Monduntergang
+ 13:59 Uhr +
+ +
+ Mondphase
+ abnehmender Mond +
+ +
+ Luftdruck
+ 1003 hPa +
+ +
+ UV-Index
+ 4 +
+ +
+ +
+ + +
+
+
+ +
+
+
+ +
+ +

Wetter Hamburg
für Montag, den 30.05.2016 im Diagramm

+
+ +
+
Temperatur °C
+
+
Lade Grafik...
+
+
+
+
Niederschlag l/m²
+
+
Lade Grafik...
+
+
+
+
Luftfeuchtigkeit %
+
+
Lade Grafik...
+
+
+ +
+
Wind/Böen Km/h
+
+
Lade Grafik...
+
+
+ +
+
Luftdruck hPa
+
+
Lade Grafik...
+
+
+ + +
+
+ +
+
+ +
+
+

Die Wettervorhersage für Montag, 30.05.2016 für Hamburg, Hamburg, Deutschland

+

Nachts kühlt es ab auf 18° (gefühlte 18°). Es wird mäßiger Wind (20 km/h) aus Nordost mit starken Böen (39 km/h) erwartet. Dabei werden 2 - 4 l/m² Niederschlag erwartet. Die Luftfeuchtigkeit beträgt nachts in Hamburg 89%, das Niederschlagsrisiko 76%.

+

Zu Tagesbeginn werden Temperaturen von bis zu 19° (gefühlt wie 20°) erreicht. Es wird mäßiger Wind (19 km/h) aus Ostnordost mit starken Böen (39 km/h) erwartet. Dabei werden mit einer Wahrscheinlichkeit von 80% 3 - 5 l/m² Niederschlag erwartet. Die Luftfeuchtigkeit beträgt 83%.

+

Gegen Mittag werden in Hamburg Höchsttemperaturen von 24° (gefühlt: 24°) erwartet. Es wird mäßiger Wind (20 km/h) aus Ost mit starken Böen (48 km/h) erwartet. Es kommt zu Niederschlagsmengen von 0 - 2 l/m², die Niederschlagswahrscheinlichkeit beträgt 49%, die Luftfeuchtigkeit 66%.

+

Am Ende des Tages werden es in Hamburg 21° (allerdings gefühlte 22°). Es wird schwacher Wind (17 km/h) aus Nordnordost mit frischen Böen (33 km/h) erwartet. Bei einer Luftfeuchtigkeit von 77% werden mit 80% Niederschläge erwartet und es wird 5 - 10 l/m² Niederschlag am Ende des Tages in Hamburg geben.

+

Die Sonne scheint in Hamburg (Hamburg, Hamburg, Deutschland) 05:00 Stunden. Die Sonne begrüßt Sie heute um 04:59 Uhr. Suchen Sie sich für 21:36 Uhr ein schönes Plätzchen und bewundern Sie den Sonnenuntergang.

+
+
+ +
+ +
+ +
+
+ + + + +
+

Wetter im Umkreis von Hamburg

+ + + + + + +
+ + Wetter Hinterdeich + + + + + Wetter Ellerbek + + +
+
+ +
+ + Wetter Glinde + + + + + Wetter Halstenbek + + +
+
+ + + +
+ + Wetter Rellingen + + + + + Wetter Stapelfeld + + +
+
+ +
+ + Wetter Seevetal + + + + + Wetter Hasloh + + +
+
+ +
+ + Wetter Tangstedt + + + + + Wetter Reinbek + + +
+
+ +
+ + Wetter Pinneberg + + + + + Wetter Braak + + +
+
+ +
+ + Wetter Wentorf + + + + + Wetter Norderstedt + + +
+
+ +
+
+ +
+
+ + + + + + + +
+ + +
+ +
+ + +
+ + +
+
+
+ +
+
+
+ +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.7.4