mirror of
https://github.com/hmalik144/Weather-apps.git
synced 2026-03-18 07:26:04 +00:00
- weathered
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.appttude.h_mal.atlas_weather.data.repository
|
||||
|
||||
import com.appttude.h_mal.atlas_weather.data.network.WeatherApi
|
||||
import com.appttude.h_mal.atlas_weather.data.prefs.LOCATION_CONST
|
||||
import com.appttude.h_mal.atlas_weather.data.prefs.PreferenceProvider
|
||||
import com.appttude.h_mal.atlas_weather.data.room.AppDatabase
|
||||
import io.mockk.MockKAnnotations
|
||||
@@ -10,9 +11,8 @@ import org.junit.Before
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
private const val MORE_THAN_FIVE_MINS = 310000L
|
||||
private const val LESS_THAN_FIVE_MINS = 290000L
|
||||
|
||||
private const val MORE_THAN_FIVE_MINS = 330000L
|
||||
private const val LESS_THAN_FIVE_MINS = 270000L
|
||||
class RepositoryImplTest {
|
||||
|
||||
lateinit var repository: RepositoryImpl
|
||||
@@ -38,7 +38,7 @@ class RepositoryImplTest {
|
||||
val location = "CurrentLocation"
|
||||
|
||||
//Act
|
||||
every { prefs.getLastSavedAt(location) } returns (System.currentTimeMillis() - LESS_THAN_FIVE_MINS)
|
||||
every { prefs.getLastSavedAt("$LOCATION_CONST$location") } returns (System.currentTimeMillis() - LESS_THAN_FIVE_MINS)
|
||||
|
||||
//Assert
|
||||
val valid: Boolean = repository.isSearchValid(location)
|
||||
@@ -51,7 +51,7 @@ class RepositoryImplTest {
|
||||
val location = "CurrentLocation"
|
||||
|
||||
//Act
|
||||
every { prefs.getLastSavedAt(location) } returns (System.currentTimeMillis() - MORE_THAN_FIVE_MINS)
|
||||
every { prefs.getLastSavedAt("$LOCATION_CONST$location") } returns (System.currentTimeMillis() - MORE_THAN_FIVE_MINS)
|
||||
|
||||
// Assert
|
||||
val valid: Boolean = repository.isSearchValid(location)
|
||||
@@ -64,7 +64,7 @@ class RepositoryImplTest {
|
||||
val location = "CurrentLocation"
|
||||
|
||||
//Act
|
||||
every { prefs.getLastSavedAt(location) } returns 0L
|
||||
every { prefs.getLastSavedAt("$LOCATION_CONST$location") } returns 0L
|
||||
|
||||
// Assert
|
||||
val valid: Boolean = repository.isSearchValid(location)
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.appttude.h_mal.atlas_weather.helper
|
||||
|
||||
import com.appttude.h_mal.atlas_weather.data.location.LocationProviderImpl
|
||||
import com.appttude.h_mal.atlas_weather.data.network.response.forecast.WeatherResponse
|
||||
import com.appttude.h_mal.atlas_weather.data.repository.Repository
|
||||
import com.appttude.h_mal.atlas_weather.data.repository.SettingsRepository
|
||||
import com.appttude.h_mal.atlas_weather.data.room.entity.CURRENT_LOCATION
|
||||
import com.appttude.h_mal.atlas_weather.data.room.entity.EntityItem
|
||||
import com.appttude.h_mal.atlas_weather.model.weather.FullWeather
|
||||
import com.google.gson.Gson
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.io.IOException
|
||||
|
||||
class ServicesHelperTest{
|
||||
|
||||
private val gson = Gson()
|
||||
|
||||
lateinit var helper: ServicesHelper
|
||||
|
||||
@MockK
|
||||
lateinit var repository: Repository
|
||||
@MockK
|
||||
lateinit var settingsRepository: SettingsRepository
|
||||
@MockK
|
||||
lateinit var locationProvider: LocationProviderImpl
|
||||
|
||||
lateinit var weatherResponse: WeatherResponse
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
helper = ServicesHelper(repository, settingsRepository, locationProvider)
|
||||
|
||||
val json = this::class.java.classLoader!!.getResource("weather_sample.json").readText()
|
||||
weatherResponse = gson.fromJson(json, WeatherResponse::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWidgetDataAsync_successfulResponse() = runBlocking{
|
||||
// Arrange
|
||||
val entityItem = EntityItem(CURRENT_LOCATION, FullWeather(weatherResponse).apply {
|
||||
temperatureUnit = "°C"
|
||||
locationString = CURRENT_LOCATION
|
||||
})
|
||||
|
||||
// Act
|
||||
coEvery { locationProvider.getCurrentLatLong() } returns Pair(weatherResponse.lat, weatherResponse.lon)
|
||||
every { repository.isSearchValid(CURRENT_LOCATION) }.returns(true)
|
||||
coEvery { repository.getWeatherFromApi(weatherResponse.lat.toString(), weatherResponse.lon.toString()) }.returns(weatherResponse)
|
||||
coEvery { locationProvider.getLocationNameFromLatLong(weatherResponse.lat, weatherResponse.lon) }.returns(CURRENT_LOCATION)
|
||||
every { repository.saveLastSavedAt(CURRENT_LOCATION) } returns Unit
|
||||
coEvery { repository.saveCurrentWeatherToRoom(entityItem) } returns Unit
|
||||
|
||||
// Assert
|
||||
val result = helper.fetchData()
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWidgetDataAsync_unsuccessfulResponse() = runBlocking{
|
||||
// Act
|
||||
coEvery { locationProvider.getCurrentLatLong() } returns Pair(0.0,0.0)
|
||||
every { repository.isSearchValid(CURRENT_LOCATION) }.returns(true)
|
||||
coEvery { repository.getWeatherFromApi("0.0", "0.0") } throws IOException("error")
|
||||
|
||||
// Assert
|
||||
val result = helper.fetchData()
|
||||
assertTrue(!result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWidgetDataAsync_invalidSearch() = runBlocking{
|
||||
// Act
|
||||
every { repository.isSearchValid(CURRENT_LOCATION) }.returns(false)
|
||||
|
||||
// Assert
|
||||
val result = helper.fetchData()
|
||||
assertTrue(!result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
{
|
||||
"lat": 51.5,
|
||||
"lon": -0.12,
|
||||
"timezone": "Europe/London",
|
||||
"timezone_offset": 0,
|
||||
"current": {
|
||||
"dt": 1608391380,
|
||||
"sunrise": 1608364972,
|
||||
"sunset": 1608393158,
|
||||
"temp": 10.53,
|
||||
"feels_like": 5.17,
|
||||
"pressure": 1006,
|
||||
"humidity": 71,
|
||||
"dew_point": 5.5,
|
||||
"uvi": 0.12,
|
||||
"clouds": 39,
|
||||
"visibility": 10000,
|
||||
"wind_speed": 6.2,
|
||||
"wind_deg": 210,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"rain": {
|
||||
"1h": 0.19
|
||||
}
|
||||
},
|
||||
"daily": [
|
||||
{
|
||||
"dt": 1608375600,
|
||||
"sunrise": 1608364972,
|
||||
"sunset": 1608393158,
|
||||
"temp": {
|
||||
"day": 11.78,
|
||||
"min": 9.1,
|
||||
"max": 12.31,
|
||||
"night": 9.1,
|
||||
"eve": 10.27,
|
||||
"morn": 10.8
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 6.46,
|
||||
"night": 5.08,
|
||||
"eve": 5.58,
|
||||
"morn": 4.63
|
||||
},
|
||||
"pressure": 1005,
|
||||
"humidity": 69,
|
||||
"dew_point": 6.42,
|
||||
"wind_speed": 6.37,
|
||||
"wind_deg": 217,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 97,
|
||||
"pop": 0.98,
|
||||
"rain": 1.69,
|
||||
"uvi": 0.53
|
||||
},
|
||||
{
|
||||
"dt": 1608462000,
|
||||
"sunrise": 1608451406,
|
||||
"sunset": 1608479581,
|
||||
"temp": {
|
||||
"day": 9.9,
|
||||
"min": 7.41,
|
||||
"max": 10.52,
|
||||
"night": 7.41,
|
||||
"eve": 8.83,
|
||||
"morn": 8.59
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 4.19,
|
||||
"night": 3.99,
|
||||
"eve": 4.55,
|
||||
"morn": 4.79
|
||||
},
|
||||
"pressure": 1013,
|
||||
"humidity": 64,
|
||||
"dew_point": 3.48,
|
||||
"wind_speed": 6.12,
|
||||
"wind_deg": 226,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 8,
|
||||
"pop": 0.58,
|
||||
"rain": 0.65,
|
||||
"uvi": 0.45
|
||||
},
|
||||
{
|
||||
"dt": 1608548400,
|
||||
"sunrise": 1608537838,
|
||||
"sunset": 1608566008,
|
||||
"temp": {
|
||||
"day": 11.06,
|
||||
"min": 7.01,
|
||||
"max": 13.57,
|
||||
"night": 13.2,
|
||||
"eve": 12.68,
|
||||
"morn": 8.59
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 6.32,
|
||||
"night": 9.99,
|
||||
"eve": 9.75,
|
||||
"morn": 4.64
|
||||
},
|
||||
"pressure": 1005,
|
||||
"humidity": 91,
|
||||
"dew_point": 9.69,
|
||||
"wind_speed": 6.7,
|
||||
"wind_deg": 185,
|
||||
"weather": [
|
||||
{
|
||||
"id": 501,
|
||||
"main": "Rain",
|
||||
"description": "moderate rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 100,
|
||||
"pop": 1,
|
||||
"rain": 7.85,
|
||||
"uvi": 0.21
|
||||
},
|
||||
{
|
||||
"dt": 1608634800,
|
||||
"sunrise": 1608624266,
|
||||
"sunset": 1608652438,
|
||||
"temp": {
|
||||
"day": 12.97,
|
||||
"min": 11.7,
|
||||
"max": 13.21,
|
||||
"night": 11.7,
|
||||
"eve": 12.37,
|
||||
"morn": 12.93
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 11.39,
|
||||
"night": 10.49,
|
||||
"eve": 10.96,
|
||||
"morn": 9.65
|
||||
},
|
||||
"pressure": 1012,
|
||||
"humidity": 83,
|
||||
"dew_point": 10.31,
|
||||
"wind_speed": 2.38,
|
||||
"wind_deg": 214,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 100,
|
||||
"pop": 1,
|
||||
"rain": 3.25,
|
||||
"uvi": 0.34
|
||||
},
|
||||
{
|
||||
"dt": 1608721200,
|
||||
"sunrise": 1608710690,
|
||||
"sunset": 1608738871,
|
||||
"temp": {
|
||||
"day": 12.28,
|
||||
"min": 10.12,
|
||||
"max": 12.62,
|
||||
"night": 10.12,
|
||||
"eve": 10.12,
|
||||
"morn": 11.73
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 7.48,
|
||||
"night": 6.73,
|
||||
"eve": 6.6,
|
||||
"morn": 8.15
|
||||
},
|
||||
"pressure": 1006,
|
||||
"humidity": 64,
|
||||
"dew_point": 5.76,
|
||||
"wind_speed": 5.45,
|
||||
"wind_deg": 224,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 97,
|
||||
"pop": 0.94,
|
||||
"rain": 2.52,
|
||||
"uvi": 0.52
|
||||
},
|
||||
{
|
||||
"dt": 1608811200,
|
||||
"sunrise": 1608797112,
|
||||
"sunset": 1608825307,
|
||||
"temp": {
|
||||
"day": 7.3,
|
||||
"min": 4.66,
|
||||
"max": 8.32,
|
||||
"night": 4.66,
|
||||
"eve": 5.76,
|
||||
"morn": 5.85
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 0.36,
|
||||
"night": -1.25,
|
||||
"eve": -0.31,
|
||||
"morn": -2.46
|
||||
},
|
||||
"pressure": 1020,
|
||||
"humidity": 60,
|
||||
"dew_point": 0.15,
|
||||
"wind_speed": 7.09,
|
||||
"wind_deg": 5,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 85,
|
||||
"pop": 0.52,
|
||||
"rain": 0.6,
|
||||
"uvi": 1
|
||||
},
|
||||
{
|
||||
"dt": 1608897600,
|
||||
"sunrise": 1608883530,
|
||||
"sunset": 1608911747,
|
||||
"temp": {
|
||||
"day": 4.12,
|
||||
"min": 2.2,
|
||||
"max": 4.63,
|
||||
"night": 2.97,
|
||||
"eve": 3.44,
|
||||
"morn": 2.28
|
||||
},
|
||||
"feels_like": {
|
||||
"day": -0.33,
|
||||
"night": -0.43,
|
||||
"eve": -0.1,
|
||||
"morn": -2.82
|
||||
},
|
||||
"pressure": 1033,
|
||||
"humidity": 70,
|
||||
"dew_point": -3.09,
|
||||
"wind_speed": 3.35,
|
||||
"wind_deg": 334,
|
||||
"weather": [
|
||||
{
|
||||
"id": 800,
|
||||
"main": "Clear",
|
||||
"description": "clear sky",
|
||||
"icon": "01d"
|
||||
}
|
||||
],
|
||||
"clouds": 0,
|
||||
"pop": 0,
|
||||
"uvi": 1
|
||||
},
|
||||
{
|
||||
"dt": 1608984000,
|
||||
"sunrise": 1608969944,
|
||||
"sunset": 1608998190,
|
||||
"temp": {
|
||||
"day": 6.03,
|
||||
"min": 2.76,
|
||||
"max": 6.92,
|
||||
"night": 6.92,
|
||||
"eve": 6.45,
|
||||
"morn": 3.59
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 0.49,
|
||||
"night": -0.96,
|
||||
"eve": -0.28,
|
||||
"morn": -0.44
|
||||
},
|
||||
"pressure": 1024,
|
||||
"humidity": 69,
|
||||
"dew_point": 0.84,
|
||||
"wind_speed": 5.25,
|
||||
"wind_deg": 251,
|
||||
"weather": [
|
||||
{
|
||||
"id": 804,
|
||||
"main": "Clouds",
|
||||
"description": "overcast clouds",
|
||||
"icon": "04d"
|
||||
}
|
||||
],
|
||||
"clouds": 100,
|
||||
"pop": 0,
|
||||
"uvi": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package com.appttude.h_mal.atlas_weather.viewmodel
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
|
||||
import com.appttude.h_mal.atlas_weather.data.network.response.forecast.WeatherResponse
|
||||
import com.appttude.h_mal.atlas_weather.data.repository.Repository
|
||||
import com.appttude.h_mal.atlas_weather.data.room.entity.EntityItem
|
||||
import com.appttude.h_mal.atlas_weather.utils.Event
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.impl.annotations.RelaxedMockK
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestRule
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class MainViewModelTest{
|
||||
|
||||
@get:Rule
|
||||
var rule: TestRule = InstantTaskExecutorRule()
|
||||
|
||||
lateinit var mainViewModel: MainViewModel
|
||||
|
||||
@MockK(relaxed = true)
|
||||
lateinit var repository: Repository
|
||||
|
||||
@MockK
|
||||
lateinit var locationProvider: LocationProvider
|
||||
|
||||
@RelaxedMockK
|
||||
lateinit var mockedLiveData: LiveData<EntityItem>
|
||||
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
mainViewModel = MainViewModel(locationProvider, repository)
|
||||
every { repository.loadCurrentWeatherFromRoom("CurrentLocation") } answers { mockedLiveData }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fetchData_workingLocation_successfulOperation() = runBlocking{
|
||||
val observer = mockk<Observer<Event<Boolean>>>(relaxed = true)
|
||||
val mockResponse = mockk<WeatherResponse>()
|
||||
mainViewModel.operationState.observeForever(observer)
|
||||
|
||||
// Act
|
||||
every { observer.onChanged(Event(false)) }
|
||||
every { locationProvider.getLatLong() } returns Pair(0.00, 0.00)
|
||||
coEvery { repository.getWeatherFromApi("0.00", "0.00") } returns mockResponse
|
||||
|
||||
|
||||
// Assert
|
||||
mainViewModel.fetchData()
|
||||
delay(50)
|
||||
assertEquals(mainViewModel.operationState.value?.getContentIfNotHandled(), false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.appttude.h_mal.atlas_weather.viewmodel
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import com.appttude.h_mal.atlas_weather.data.location.LocationProviderImpl
|
||||
import com.appttude.h_mal.atlas_weather.data.repository.Repository
|
||||
import com.appttude.h_mal.atlas_weather.data.room.entity.CURRENT_LOCATION
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
|
||||
class WorldViewModelTest {
|
||||
@get:Rule
|
||||
val rule = InstantTaskExecutorRule()
|
||||
|
||||
lateinit var viewModel: WorldViewModel
|
||||
|
||||
@MockK(relaxed = true)
|
||||
lateinit var repository: Repository
|
||||
|
||||
@MockK
|
||||
lateinit var locationProvider: LocationProviderImpl
|
||||
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
viewModel = WorldViewModel(locationProvider, repository)
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun name() {
|
||||
val location = CURRENT_LOCATION
|
||||
|
||||
viewModel.fetchDataForSingleLocation(location)
|
||||
|
||||
assertEquals(viewModel.operationRefresh.getOrAwaitValue()?.getContentIfNotHandled(), true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Copyright 2019 Google LLC.
|
||||
SPDX-License-Identifier: Apache-2.0 */
|
||||
fun <T> LiveData<T>.getOrAwaitValue(
|
||||
time: Long = 2,
|
||||
timeUnit: TimeUnit = TimeUnit.SECONDS
|
||||
): T {
|
||||
var data: T? = null
|
||||
val latch = CountDownLatch(1)
|
||||
val observer = object : Observer<T> {
|
||||
override fun onChanged(o: T?) {
|
||||
data = o
|
||||
latch.countDown()
|
||||
this@getOrAwaitValue.removeObserver(this)
|
||||
}
|
||||
}
|
||||
|
||||
this.observeForever(observer)
|
||||
|
||||
// Don't wait indefinitely if the LiveData is not set.
|
||||
if (!latch.await(time, timeUnit)) {
|
||||
throw TimeoutException("LiveData value was never set.")
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return data as T
|
||||
}
|
||||
317
app/src/test/resources/weather_sample.json
Normal file
317
app/src/test/resources/weather_sample.json
Normal file
@@ -0,0 +1,317 @@
|
||||
{
|
||||
"lat": 51.5,
|
||||
"lon": -0.12,
|
||||
"timezone": "Europe/London",
|
||||
"timezone_offset": 0,
|
||||
"current": {
|
||||
"dt": 1608394319,
|
||||
"sunrise": 1608364972,
|
||||
"sunset": 1608393158,
|
||||
"temp": 9.42,
|
||||
"feels_like": 4.9,
|
||||
"pressure": 1007,
|
||||
"humidity": 91,
|
||||
"dew_point": 8.03,
|
||||
"uvi": 0,
|
||||
"clouds": 33,
|
||||
"visibility": 10000,
|
||||
"wind_speed": 5.8,
|
||||
"wind_deg": 215,
|
||||
"weather": [
|
||||
{
|
||||
"id": 802,
|
||||
"main": "Clouds",
|
||||
"description": "scattered clouds",
|
||||
"icon": "03n"
|
||||
}
|
||||
]
|
||||
},
|
||||
"daily": [
|
||||
{
|
||||
"dt": 1608375600,
|
||||
"sunrise": 1608364972,
|
||||
"sunset": 1608393158,
|
||||
"temp": {
|
||||
"day": 11.78,
|
||||
"min": 9.1,
|
||||
"max": 12.31,
|
||||
"night": 9.1,
|
||||
"eve": 9.8,
|
||||
"morn": 10.8
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 6.46,
|
||||
"night": 5.08,
|
||||
"eve": 5.47,
|
||||
"morn": 4.63
|
||||
},
|
||||
"pressure": 1005,
|
||||
"humidity": 69,
|
||||
"dew_point": 6.42,
|
||||
"wind_speed": 6.37,
|
||||
"wind_deg": 217,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 97,
|
||||
"pop": 0.98,
|
||||
"rain": 1.55,
|
||||
"uvi": 0.53
|
||||
},
|
||||
{
|
||||
"dt": 1608462000,
|
||||
"sunrise": 1608451406,
|
||||
"sunset": 1608479581,
|
||||
"temp": {
|
||||
"day": 9.9,
|
||||
"min": 7.41,
|
||||
"max": 10.52,
|
||||
"night": 7.41,
|
||||
"eve": 8.83,
|
||||
"morn": 8.59
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 4.19,
|
||||
"night": 3.99,
|
||||
"eve": 4.55,
|
||||
"morn": 4.79
|
||||
},
|
||||
"pressure": 1013,
|
||||
"humidity": 64,
|
||||
"dew_point": 3.48,
|
||||
"wind_speed": 6.12,
|
||||
"wind_deg": 226,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 8,
|
||||
"pop": 0.58,
|
||||
"rain": 0.65,
|
||||
"uvi": 0.45
|
||||
},
|
||||
{
|
||||
"dt": 1608548400,
|
||||
"sunrise": 1608537838,
|
||||
"sunset": 1608566008,
|
||||
"temp": {
|
||||
"day": 11.06,
|
||||
"min": 7.01,
|
||||
"max": 13.57,
|
||||
"night": 13.2,
|
||||
"eve": 12.68,
|
||||
"morn": 8.59
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 6.32,
|
||||
"night": 9.99,
|
||||
"eve": 9.75,
|
||||
"morn": 4.64
|
||||
},
|
||||
"pressure": 1005,
|
||||
"humidity": 91,
|
||||
"dew_point": 9.69,
|
||||
"wind_speed": 6.7,
|
||||
"wind_deg": 185,
|
||||
"weather": [
|
||||
{
|
||||
"id": 501,
|
||||
"main": "Rain",
|
||||
"description": "moderate rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 100,
|
||||
"pop": 1,
|
||||
"rain": 7.85,
|
||||
"uvi": 0.21
|
||||
},
|
||||
{
|
||||
"dt": 1608634800,
|
||||
"sunrise": 1608624266,
|
||||
"sunset": 1608652438,
|
||||
"temp": {
|
||||
"day": 12.97,
|
||||
"min": 11.7,
|
||||
"max": 13.21,
|
||||
"night": 11.7,
|
||||
"eve": 12.37,
|
||||
"morn": 12.93
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 11.39,
|
||||
"night": 10.49,
|
||||
"eve": 10.96,
|
||||
"morn": 9.65
|
||||
},
|
||||
"pressure": 1012,
|
||||
"humidity": 83,
|
||||
"dew_point": 10.31,
|
||||
"wind_speed": 2.38,
|
||||
"wind_deg": 214,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 100,
|
||||
"pop": 1,
|
||||
"rain": 3.25,
|
||||
"uvi": 0.34
|
||||
},
|
||||
{
|
||||
"dt": 1608721200,
|
||||
"sunrise": 1608710690,
|
||||
"sunset": 1608738871,
|
||||
"temp": {
|
||||
"day": 12.28,
|
||||
"min": 10.12,
|
||||
"max": 12.62,
|
||||
"night": 10.12,
|
||||
"eve": 10.12,
|
||||
"morn": 11.73
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 7.48,
|
||||
"night": 6.73,
|
||||
"eve": 6.6,
|
||||
"morn": 8.15
|
||||
},
|
||||
"pressure": 1006,
|
||||
"humidity": 64,
|
||||
"dew_point": 5.76,
|
||||
"wind_speed": 5.45,
|
||||
"wind_deg": 224,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 97,
|
||||
"pop": 0.94,
|
||||
"rain": 2.52,
|
||||
"uvi": 0.52
|
||||
},
|
||||
{
|
||||
"dt": 1608811200,
|
||||
"sunrise": 1608797112,
|
||||
"sunset": 1608825307,
|
||||
"temp": {
|
||||
"day": 7.3,
|
||||
"min": 4.66,
|
||||
"max": 8.32,
|
||||
"night": 4.66,
|
||||
"eve": 5.76,
|
||||
"morn": 5.85
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 0.36,
|
||||
"night": -1.25,
|
||||
"eve": -0.31,
|
||||
"morn": -2.46
|
||||
},
|
||||
"pressure": 1020,
|
||||
"humidity": 60,
|
||||
"dew_point": 0.15,
|
||||
"wind_speed": 7.09,
|
||||
"wind_deg": 5,
|
||||
"weather": [
|
||||
{
|
||||
"id": 500,
|
||||
"main": "Rain",
|
||||
"description": "light rain",
|
||||
"icon": "10d"
|
||||
}
|
||||
],
|
||||
"clouds": 85,
|
||||
"pop": 0.52,
|
||||
"rain": 0.6,
|
||||
"uvi": 1
|
||||
},
|
||||
{
|
||||
"dt": 1608897600,
|
||||
"sunrise": 1608883530,
|
||||
"sunset": 1608911747,
|
||||
"temp": {
|
||||
"day": 4.12,
|
||||
"min": 2.2,
|
||||
"max": 4.63,
|
||||
"night": 2.97,
|
||||
"eve": 3.44,
|
||||
"morn": 2.28
|
||||
},
|
||||
"feels_like": {
|
||||
"day": -0.33,
|
||||
"night": -0.43,
|
||||
"eve": -0.1,
|
||||
"morn": -2.82
|
||||
},
|
||||
"pressure": 1033,
|
||||
"humidity": 70,
|
||||
"dew_point": -3.09,
|
||||
"wind_speed": 3.35,
|
||||
"wind_deg": 334,
|
||||
"weather": [
|
||||
{
|
||||
"id": 800,
|
||||
"main": "Clear",
|
||||
"description": "clear sky",
|
||||
"icon": "01d"
|
||||
}
|
||||
],
|
||||
"clouds": 0,
|
||||
"pop": 0,
|
||||
"uvi": 1
|
||||
},
|
||||
{
|
||||
"dt": 1608984000,
|
||||
"sunrise": 1608969944,
|
||||
"sunset": 1608998190,
|
||||
"temp": {
|
||||
"day": 6.03,
|
||||
"min": 2.76,
|
||||
"max": 6.92,
|
||||
"night": 6.92,
|
||||
"eve": 6.45,
|
||||
"morn": 3.59
|
||||
},
|
||||
"feels_like": {
|
||||
"day": 0.49,
|
||||
"night": -0.96,
|
||||
"eve": -0.28,
|
||||
"morn": -0.44
|
||||
},
|
||||
"pressure": 1024,
|
||||
"humidity": 69,
|
||||
"dew_point": 0.84,
|
||||
"wind_speed": 5.25,
|
||||
"wind_deg": 251,
|
||||
"weather": [
|
||||
{
|
||||
"id": 804,
|
||||
"main": "Clouds",
|
||||
"description": "overcast clouds",
|
||||
"icon": "04d"
|
||||
}
|
||||
],
|
||||
"clouds": 100,
|
||||
"pop": 0,
|
||||
"uvi": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user