Replace joda.time by java.time
This commit is contained in:
parent
3af1220666
commit
7abec11b55
@ -47,5 +47,4 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.moshi)
|
implementation(libs.moshi)
|
||||||
implementation(libs.jsoup)
|
implementation(libs.jsoup)
|
||||||
implementation(libs.jodatime)
|
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@ import com.gitlab.mvysny.konsumexml.Konsumer
|
|||||||
import com.gitlab.mvysny.konsumexml.Names
|
import com.gitlab.mvysny.konsumexml.Names
|
||||||
import com.gitlab.mvysny.konsumexml.allChildrenAutoIgnore
|
import com.gitlab.mvysny.konsumexml.allChildrenAutoIgnore
|
||||||
import com.readrops.api.localfeed.XmlAdapter
|
import com.readrops.api.localfeed.XmlAdapter
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.api.utils.exceptions.ParseException
|
import com.readrops.api.utils.exceptions.ParseException
|
||||||
import com.readrops.api.utils.extensions.nonNullText
|
import com.readrops.api.utils.extensions.nonNullText
|
||||||
import com.readrops.api.utils.extensions.nullableText
|
import com.readrops.api.utils.extensions.nullableText
|
||||||
import com.readrops.api.utils.extensions.nullableTextRecursively
|
import com.readrops.api.utils.extensions.nullableTextRecursively
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
import org.joda.time.LocalDateTime
|
import com.readrops.db.util.DateUtils
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
class ATOMItemAdapter : XmlAdapter<Item> {
|
class ATOMItemAdapter : XmlAdapter<Item> {
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
package com.readrops.api.localfeed.json
|
package com.readrops.api.localfeed.json
|
||||||
|
|
||||||
import com.readrops.api.localfeed.XmlAdapter.Companion.AUTHORS_MAX
|
import com.readrops.api.localfeed.XmlAdapter.Companion.AUTHORS_MAX
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.api.utils.exceptions.ParseException
|
import com.readrops.api.utils.exceptions.ParseException
|
||||||
import com.readrops.api.utils.extensions.nextNonEmptyString
|
import com.readrops.api.utils.extensions.nextNonEmptyString
|
||||||
import com.readrops.api.utils.extensions.nextNullableString
|
import com.readrops.api.utils.extensions.nextNullableString
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import com.squareup.moshi.JsonAdapter
|
import com.squareup.moshi.JsonAdapter
|
||||||
import com.squareup.moshi.JsonReader
|
import com.squareup.moshi.JsonReader
|
||||||
import com.squareup.moshi.JsonWriter
|
import com.squareup.moshi.JsonWriter
|
||||||
import org.joda.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
class JSONItemsAdapter : JsonAdapter<List<Item>>() {
|
class JSONItemsAdapter : JsonAdapter<List<Item>>() {
|
||||||
|
|
||||||
|
@ -5,13 +5,13 @@ import com.gitlab.mvysny.konsumexml.Names
|
|||||||
import com.gitlab.mvysny.konsumexml.allChildrenAutoIgnore
|
import com.gitlab.mvysny.konsumexml.allChildrenAutoIgnore
|
||||||
import com.readrops.api.localfeed.XmlAdapter
|
import com.readrops.api.localfeed.XmlAdapter
|
||||||
import com.readrops.api.localfeed.XmlAdapter.Companion.AUTHORS_MAX
|
import com.readrops.api.localfeed.XmlAdapter.Companion.AUTHORS_MAX
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.api.utils.exceptions.ParseException
|
import com.readrops.api.utils.exceptions.ParseException
|
||||||
import com.readrops.api.utils.extensions.nonNullText
|
import com.readrops.api.utils.extensions.nonNullText
|
||||||
import com.readrops.api.utils.extensions.nullableText
|
import com.readrops.api.utils.extensions.nullableText
|
||||||
import com.readrops.api.utils.extensions.nullableTextRecursively
|
import com.readrops.api.utils.extensions.nullableTextRecursively
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
import org.joda.time.LocalDateTime
|
import com.readrops.db.util.DateUtils
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
class RSS1ItemAdapter : XmlAdapter<Item> {
|
class RSS1ItemAdapter : XmlAdapter<Item> {
|
||||||
|
|
||||||
|
@ -7,13 +7,13 @@ import com.gitlab.mvysny.konsumexml.allChildrenAutoIgnore
|
|||||||
import com.readrops.api.localfeed.XmlAdapter
|
import com.readrops.api.localfeed.XmlAdapter
|
||||||
import com.readrops.api.localfeed.XmlAdapter.Companion.AUTHORS_MAX
|
import com.readrops.api.localfeed.XmlAdapter.Companion.AUTHORS_MAX
|
||||||
import com.readrops.api.utils.ApiUtils
|
import com.readrops.api.utils.ApiUtils
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.api.utils.exceptions.ParseException
|
import com.readrops.api.utils.exceptions.ParseException
|
||||||
import com.readrops.api.utils.extensions.nonNullText
|
import com.readrops.api.utils.extensions.nonNullText
|
||||||
import com.readrops.api.utils.extensions.nullableText
|
import com.readrops.api.utils.extensions.nullableText
|
||||||
import com.readrops.api.utils.extensions.nullableTextRecursively
|
import com.readrops.api.utils.extensions.nullableTextRecursively
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
import org.joda.time.LocalDateTime
|
import com.readrops.db.util.DateUtils
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
class RSS2ItemAdapter : XmlAdapter<Item> {
|
class RSS2ItemAdapter : XmlAdapter<Item> {
|
||||||
|
|
||||||
|
@ -6,11 +6,10 @@ import com.readrops.api.utils.exceptions.ParseException
|
|||||||
import com.readrops.api.utils.extensions.nextNonEmptyString
|
import com.readrops.api.utils.extensions.nextNonEmptyString
|
||||||
import com.readrops.api.utils.extensions.nextNullableString
|
import com.readrops.api.utils.extensions.nextNullableString
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import com.squareup.moshi.JsonAdapter
|
import com.squareup.moshi.JsonAdapter
|
||||||
import com.squareup.moshi.JsonReader
|
import com.squareup.moshi.JsonReader
|
||||||
import com.squareup.moshi.JsonWriter
|
import com.squareup.moshi.JsonWriter
|
||||||
import org.joda.time.DateTimeZone
|
|
||||||
import org.joda.time.LocalDateTime
|
|
||||||
|
|
||||||
class FreshRSSItemsAdapter : JsonAdapter<List<Item>>() {
|
class FreshRSSItemsAdapter : JsonAdapter<List<Item>>() {
|
||||||
|
|
||||||
@ -46,8 +45,7 @@ class FreshRSSItemsAdapter : JsonAdapter<List<Item>>() {
|
|||||||
with(item) {
|
with(item) {
|
||||||
when (reader.selectName(NAMES)) {
|
when (reader.selectName(NAMES)) {
|
||||||
0 -> remoteId = reader.nextNonEmptyString()
|
0 -> remoteId = reader.nextNonEmptyString()
|
||||||
1 -> pubDate = LocalDateTime(reader.nextLong() * 1000L,
|
1 -> pubDate = DateUtils.fromEpochSeconds(reader.nextLong())
|
||||||
DateTimeZone.getDefault())
|
|
||||||
2 -> title = reader.nextNonEmptyString()
|
2 -> title = reader.nextNonEmptyString()
|
||||||
3 -> content = getContent(reader)
|
3 -> content = getContent(reader)
|
||||||
4 -> link = getLink(reader)
|
4 -> link = getLink(reader)
|
||||||
|
@ -6,11 +6,10 @@ import com.readrops.api.utils.exceptions.ParseException
|
|||||||
import com.readrops.api.utils.extensions.nextNonEmptyString
|
import com.readrops.api.utils.extensions.nextNonEmptyString
|
||||||
import com.readrops.api.utils.extensions.nextNullableString
|
import com.readrops.api.utils.extensions.nextNullableString
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import com.squareup.moshi.JsonAdapter
|
import com.squareup.moshi.JsonAdapter
|
||||||
import com.squareup.moshi.JsonReader
|
import com.squareup.moshi.JsonReader
|
||||||
import com.squareup.moshi.JsonWriter
|
import com.squareup.moshi.JsonWriter
|
||||||
import org.joda.time.DateTimeZone
|
|
||||||
import org.joda.time.LocalDateTime
|
|
||||||
|
|
||||||
class NextcloudNewsItemsAdapter : JsonAdapter<List<Item>>() {
|
class NextcloudNewsItemsAdapter : JsonAdapter<List<Item>>() {
|
||||||
|
|
||||||
@ -42,7 +41,7 @@ class NextcloudNewsItemsAdapter : JsonAdapter<List<Item>>() {
|
|||||||
1 -> link = reader.nextNullableString()
|
1 -> link = reader.nextNullableString()
|
||||||
2 -> title = reader.nextNonEmptyString()
|
2 -> title = reader.nextNonEmptyString()
|
||||||
3 -> author = reader.nextNullableString()
|
3 -> author = reader.nextNullableString()
|
||||||
4 -> pubDate = LocalDateTime(reader.nextLong() * 1000L, DateTimeZone.getDefault())
|
4 -> pubDate = DateUtils.fromEpochSeconds(reader.nextLong())
|
||||||
5 -> content = reader.nextNullableString()
|
5 -> content = reader.nextNullableString()
|
||||||
6 -> enclosureMime = reader.nextNullableString()
|
6 -> enclosureMime = reader.nextNullableString()
|
||||||
7 -> enclosureLink = reader.nextNullableString()
|
7 -> enclosureLink = reader.nextNullableString()
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
package com.readrops.api.utils
|
|
||||||
|
|
||||||
import org.joda.time.LocalDateTime
|
|
||||||
import org.joda.time.format.DateTimeFormat
|
|
||||||
import org.joda.time.format.DateTimeFormatterBuilder
|
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
object DateUtils {
|
|
||||||
|
|
||||||
private val TAG = DateUtils::class.java.simpleName
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base of common RSS 2 date formats.
|
|
||||||
* Examples :
|
|
||||||
* Fri, 04 Jan 2019 22:21:46 GMT
|
|
||||||
* Fri, 04 Jan 2019 22:21:46 +0000
|
|
||||||
*/
|
|
||||||
private const val RSS_2_BASE_PATTERN = "EEE, dd MMM yyyy HH:mm:ss"
|
|
||||||
|
|
||||||
private const val GMT_PATTERN = "ZZZ"
|
|
||||||
|
|
||||||
private const val OFFSET_PATTERN = "Z"
|
|
||||||
|
|
||||||
private const val ISO_PATTERN = ".SSSZZ"
|
|
||||||
|
|
||||||
private const val EDT_PATTERN = "zzz"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Date pattern for format : 2019-01-04T22:21:46+00:00
|
|
||||||
*/
|
|
||||||
private const val ATOM_JSON_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun parse(value: String?): LocalDateTime? = if (value == null) {
|
|
||||||
null
|
|
||||||
} else try {
|
|
||||||
val formatter = DateTimeFormatterBuilder()
|
|
||||||
.appendOptional(DateTimeFormat.forPattern("$RSS_2_BASE_PATTERN ").parser) // with timezone
|
|
||||||
.appendOptional(DateTimeFormat.forPattern(RSS_2_BASE_PATTERN).parser) // no timezone, important order here
|
|
||||||
.appendOptional(DateTimeFormat.forPattern(ATOM_JSON_DATE_FORMAT).parser)
|
|
||||||
.appendOptional(DateTimeFormat.forPattern(GMT_PATTERN).parser)
|
|
||||||
.appendOptional(DateTimeFormat.forPattern(OFFSET_PATTERN).parser)
|
|
||||||
.appendOptional(DateTimeFormat.forPattern(ISO_PATTERN).parser)
|
|
||||||
.appendOptional(DateTimeFormat.forPattern(EDT_PATTERN).parser)
|
|
||||||
.toFormatter()
|
|
||||||
.withLocale(Locale.ENGLISH)
|
|
||||||
.withOffsetParsed()
|
|
||||||
|
|
||||||
formatter.parseLocalDateTime(value)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun formattedDateByLocal(dateTime: LocalDateTime): String {
|
|
||||||
return DateTimeFormat.mediumDate()
|
|
||||||
.withLocale(Locale.getDefault())
|
|
||||||
.print(dateTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun formattedDateTimeByLocal(dateTime: LocalDateTime): String {
|
|
||||||
return DateTimeFormat.forPattern("dd MMM yyyy · HH:mm")
|
|
||||||
.withLocale(Locale.getDefault())
|
|
||||||
.print(dateTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun formattedDate(dateTime: LocalDateTime): String {
|
|
||||||
val pattern = if (dateTime.year != LocalDateTime.now().year) {
|
|
||||||
"dd MMMM yyyy"
|
|
||||||
} else {
|
|
||||||
"dd MMMM"
|
|
||||||
}
|
|
||||||
|
|
||||||
return DateTimeFormat.forPattern(pattern)
|
|
||||||
.withLocale(Locale.getDefault())
|
|
||||||
.print(dateTime)
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,8 +2,8 @@ package com.readrops.api.localfeed.atom
|
|||||||
|
|
||||||
import com.gitlab.mvysny.konsumexml.konsumeXml
|
import com.gitlab.mvysny.konsumexml.konsumeXml
|
||||||
import com.readrops.api.TestUtils
|
import com.readrops.api.TestUtils
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.api.utils.exceptions.ParseException
|
import com.readrops.api.utils.exceptions.ParseException
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import junit.framework.TestCase.assertEquals
|
import junit.framework.TestCase.assertEquals
|
||||||
import org.junit.Assert.assertThrows
|
import org.junit.Assert.assertThrows
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package com.readrops.api.localfeed.json
|
package com.readrops.api.localfeed.json
|
||||||
|
|
||||||
import com.readrops.api.TestUtils
|
import com.readrops.api.TestUtils
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.api.utils.exceptions.ParseException
|
import com.readrops.api.utils.exceptions.ParseException
|
||||||
import com.readrops.db.entities.Feed
|
import com.readrops.db.entities.Feed
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
import com.squareup.moshi.Types
|
import com.squareup.moshi.Types
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
|
@ -2,8 +2,8 @@ package com.readrops.api.localfeed.rss1
|
|||||||
|
|
||||||
import com.gitlab.mvysny.konsumexml.konsumeXml
|
import com.gitlab.mvysny.konsumexml.konsumeXml
|
||||||
import com.readrops.api.TestUtils
|
import com.readrops.api.TestUtils
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.api.utils.exceptions.ParseException
|
import com.readrops.api.utils.exceptions.ParseException
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import junit.framework.Assert.assertEquals
|
import junit.framework.Assert.assertEquals
|
||||||
import junit.framework.Assert.assertNotNull
|
import junit.framework.Assert.assertNotNull
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
|
@ -2,8 +2,8 @@ package com.readrops.api.localfeed.rss2
|
|||||||
|
|
||||||
import com.gitlab.mvysny.konsumexml.konsumeXml
|
import com.gitlab.mvysny.konsumexml.konsumeXml
|
||||||
import com.readrops.api.TestUtils
|
import com.readrops.api.TestUtils
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.api.utils.exceptions.ParseException
|
import com.readrops.api.utils.exceptions.ParseException
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import junit.framework.TestCase.assertEquals
|
import junit.framework.TestCase.assertEquals
|
||||||
import junit.framework.TestCase.assertTrue
|
import junit.framework.TestCase.assertTrue
|
||||||
|
@ -2,12 +2,12 @@ package com.readrops.api.services.freshrss.adapters
|
|||||||
|
|
||||||
import com.readrops.api.TestUtils
|
import com.readrops.api.TestUtils
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
import com.squareup.moshi.Types
|
import com.squareup.moshi.Types
|
||||||
import junit.framework.TestCase.assertEquals
|
import junit.framework.TestCase.assertEquals
|
||||||
import junit.framework.TestCase.assertNotNull
|
import junit.framework.TestCase.assertNotNull
|
||||||
import okio.Buffer
|
import okio.Buffer
|
||||||
import org.joda.time.LocalDateTime
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class FreshRSSItemsAdapterTest {
|
class FreshRSSItemsAdapterTest {
|
||||||
@ -29,7 +29,7 @@ class FreshRSSItemsAdapterTest {
|
|||||||
assertNotNull(content)
|
assertNotNull(content)
|
||||||
assertEquals(link, "http://feedproxy.google.com/~r/d0od/~3/4Zk-fncSuek/adwaita-borderless-theme-in-development-gnome-41")
|
assertEquals(link, "http://feedproxy.google.com/~r/d0od/~3/4Zk-fncSuek/adwaita-borderless-theme-in-development-gnome-41")
|
||||||
assertEquals(author, "Joey Sneddon")
|
assertEquals(author, "Joey Sneddon")
|
||||||
assertEquals(pubDate, LocalDateTime(1625234040 * 1000L))
|
assertEquals(pubDate, DateUtils.fromEpochSeconds(1625234040))
|
||||||
assertEquals(isRead, false)
|
assertEquals(isRead, false)
|
||||||
assertEquals(isStarred, false)
|
assertEquals(isStarred, false)
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ package com.readrops.api.services.nextcloudnews.adapters
|
|||||||
|
|
||||||
import com.readrops.api.TestUtils
|
import com.readrops.api.TestUtils
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
import com.squareup.moshi.Types
|
import com.squareup.moshi.Types
|
||||||
import junit.framework.TestCase.assertEquals
|
import junit.framework.TestCase.assertEquals
|
||||||
import okio.Buffer
|
import okio.Buffer
|
||||||
import org.joda.time.LocalDateTime
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class NextcloudNewsItemsAdapterTest {
|
class NextcloudNewsItemsAdapterTest {
|
||||||
@ -32,7 +32,7 @@ class NextcloudNewsItemsAdapterTest {
|
|||||||
assertEquals(feedRemoteId, "67")
|
assertEquals(feedRemoteId, "67")
|
||||||
assertEquals(isRead, false)
|
assertEquals(isRead, false)
|
||||||
assertEquals(isStarred, false)
|
assertEquals(isStarred, false)
|
||||||
assertEquals(pubDate, LocalDateTime(1367270544000))
|
assertEquals(pubDate, DateUtils.fromEpochSeconds(1367270544))
|
||||||
assertEquals(imageLink, null)
|
assertEquals(imageLink, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
package com.readrops.api.utils;
|
|
||||||
|
|
||||||
import org.joda.time.LocalDateTime;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
public class DateUtilsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void rssDateTest() {
|
|
||||||
LocalDateTime dateTime = new LocalDateTime(2019, 1, 4, 22, 21, 46);
|
|
||||||
|
|
||||||
assertEquals(0, dateTime.compareTo(DateUtils.parse("Fri, 04 Jan 2019 22:21:46 GMT")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void rssDate2Test() {
|
|
||||||
LocalDateTime dateTime = new LocalDateTime(2019, 1, 4, 22, 21, 46);
|
|
||||||
|
|
||||||
assertEquals(0, dateTime.compareTo(DateUtils.parse("Fri, 04 Jan 2019 22:21:46 +0000")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void rssDate3Test() {
|
|
||||||
LocalDateTime dateTime = new LocalDateTime(2019, 1, 4, 22, 21, 46);
|
|
||||||
|
|
||||||
assertEquals(0, dateTime.compareTo(DateUtils.parse("Fri, 04 Jan 2019 22:21:46")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void atomJsonDateTest() {
|
|
||||||
LocalDateTime dateTime = new LocalDateTime(2019, 1, 4, 22, 21, 46);
|
|
||||||
|
|
||||||
assertEquals(0, dateTime.compareTo(DateUtils.parse("2019-01-04T22:21:46+00:00")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void atomJsonDate2Test() {
|
|
||||||
LocalDateTime dateTime = new LocalDateTime(2019, 1, 4, 22, 21, 46);
|
|
||||||
|
|
||||||
assertEquals(0, dateTime.compareTo(DateUtils.parse("2019-01-04T22:21:46-0000")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isoPatternTest() {
|
|
||||||
LocalDateTime dateTime = new LocalDateTime(2020, 6, 30, 11, 39, 37, 206);
|
|
||||||
|
|
||||||
assertEquals(0, dateTime.compareTo(DateUtils.parse("2020-06-30T11:39:37.206-07:00")));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void edtPatternTest() {
|
|
||||||
LocalDateTime dateTime = new LocalDateTime(2020, 7, 17, 16, 30, 0);
|
|
||||||
|
|
||||||
assertEquals(0, dateTime.compareTo(DateUtils.parse("Fri, 17 Jul 2020 16:30:00 EDT")));
|
|
||||||
}
|
|
||||||
}
|
|
@ -61,7 +61,6 @@ dependencies {
|
|||||||
implementation(libs.browser)
|
implementation(libs.browser)
|
||||||
|
|
||||||
implementation(libs.jsoup)
|
implementation(libs.jsoup)
|
||||||
implementation(libs.jodatime)
|
|
||||||
|
|
||||||
testImplementation(libs.junit4)
|
testImplementation(libs.junit4)
|
||||||
androidTestImplementation(libs.bundles.test)
|
androidTestImplementation(libs.bundles.test)
|
||||||
|
@ -13,7 +13,7 @@ import com.readrops.db.entities.account.AccountType
|
|||||||
import com.readrops.db.filters.MainFilter
|
import com.readrops.db.filters.MainFilter
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.joda.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
@ -12,7 +12,7 @@ import com.readrops.db.entities.Item
|
|||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import com.readrops.db.entities.account.AccountType
|
import com.readrops.db.entities.account.AccountType
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.joda.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
|
@ -52,7 +52,6 @@ import androidx.core.view.children
|
|||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import cafe.adriel.voyager.koin.getScreenModel
|
import cafe.adriel.voyager.koin.getScreenModel
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.app.R
|
import com.readrops.app.R
|
||||||
import com.readrops.app.item.view.ItemNestedScrollView
|
import com.readrops.app.item.view.ItemNestedScrollView
|
||||||
import com.readrops.app.item.view.ItemWebView
|
import com.readrops.app.item.view.ItemWebView
|
||||||
@ -63,6 +62,7 @@ import com.readrops.app.util.theme.MediumSpacer
|
|||||||
import com.readrops.app.util.theme.ShortSpacer
|
import com.readrops.app.util.theme.ShortSpacer
|
||||||
import com.readrops.app.util.theme.spacing
|
import com.readrops.app.util.theme.spacing
|
||||||
import com.readrops.db.pojo.ItemWithFeed
|
import com.readrops.db.pojo.ItemWithFeed
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import com.readrops.db.entities.Folder
|
|||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
import com.readrops.db.entities.ItemState
|
import com.readrops.db.entities.ItemState
|
||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import org.joda.time.DateTime
|
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
|
|
||||||
class FreshRSSRepository(
|
class FreshRSSRepository(
|
||||||
@ -63,7 +62,7 @@ class FreshRSSRepository(
|
|||||||
syncType = SyncType.INITIAL_SYNC
|
syncType = SyncType.INITIAL_SYNC
|
||||||
}
|
}
|
||||||
|
|
||||||
val newLastModified = DateTime.now().millis / 1000L
|
val newLastModified = System.currentTimeMillis() / 1000L
|
||||||
|
|
||||||
return dataSource.synchronize(syncType, syncData, account.writeToken!!).run {
|
return dataSource.synchronize(syncType, syncData, account.writeToken!!).run {
|
||||||
insertFolders(folders)
|
insertFolders(folders)
|
||||||
|
@ -16,7 +16,6 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.joda.time.DateTime
|
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.get
|
import org.koin.core.component.get
|
||||||
|
|
||||||
@ -63,7 +62,7 @@ class NextcloudNewsRepository(
|
|||||||
SyncType.INITIAL_SYNC
|
SyncType.INITIAL_SYNC
|
||||||
}
|
}
|
||||||
|
|
||||||
val newLastModified = DateTime.now().millis / 1000L
|
val newLastModified = System.currentTimeMillis() / 1000L
|
||||||
|
|
||||||
return dataSource.synchronize(syncType, syncData).run {
|
return dataSource.synchronize(syncType, syncData).run {
|
||||||
insertFolders(folders)
|
insertFolders(folders)
|
||||||
@ -163,7 +162,6 @@ class NextcloudNewsRepository(
|
|||||||
itemsFeedsIds[item.feedRemoteId] = feedId
|
itemsFeedsIds[item.feedRemoteId] = feedId
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO itemExists request isn't the right one for this case
|
|
||||||
if (!initialSync && feedId > 0 && database.itemDao().itemExists(item.remoteId!!, feedId)) {
|
if (!initialSync && feedId > 0 && database.itemDao().itemExists(item.remoteId!!, feedId)) {
|
||||||
database.itemDao()
|
database.itemDao()
|
||||||
.updateReadAndStarState(item.remoteId!!, item.isRead, item.isStarred)
|
.updateReadAndStarState(item.remoteId!!, item.isRead, item.isStarred)
|
||||||
|
@ -6,7 +6,7 @@ import com.readrops.app.util.DefaultPreview
|
|||||||
import com.readrops.app.util.theme.ReadropsTheme
|
import com.readrops.app.util.theme.ReadropsTheme
|
||||||
import com.readrops.db.entities.Folder
|
import com.readrops.db.entities.Folder
|
||||||
import com.readrops.db.pojo.ItemWithFeed
|
import com.readrops.db.pojo.ItemWithFeed
|
||||||
import org.joda.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
enum class TimelineItemSize {
|
enum class TimelineItemSize {
|
||||||
COMPACT,
|
COMPACT,
|
||||||
|
@ -34,13 +34,13 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
import com.readrops.api.utils.DateUtils
|
|
||||||
import com.readrops.app.R
|
import com.readrops.app.R
|
||||||
import com.readrops.app.util.components.FeedIcon
|
import com.readrops.app.util.components.FeedIcon
|
||||||
import com.readrops.app.util.theme.ShortSpacer
|
import com.readrops.app.util.theme.ShortSpacer
|
||||||
import com.readrops.app.util.theme.spacing
|
import com.readrops.app.util.theme.spacing
|
||||||
import com.readrops.db.pojo.ItemWithFeed
|
import com.readrops.db.pojo.ItemWithFeed
|
||||||
import org.joda.time.LocalDateTime
|
import com.readrops.db.util.DateUtils
|
||||||
|
import java.time.LocalDateTime
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
51
app/src/test/java/com/readrops/app/DateUtilsTest.kt
Normal file
51
app/src/test/java/com/readrops/app/DateUtilsTest.kt
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package com.readrops.app
|
||||||
|
|
||||||
|
import com.readrops.db.util.DateUtils
|
||||||
|
import junit.framework.TestCase.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
class DateUtilsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rssDateTest() {
|
||||||
|
val dateTime = LocalDateTime.of(2019, 1, 4, 22, 21, 46)
|
||||||
|
assertEquals(0, dateTime.compareTo(DateUtils.parse("Fri, 04 Jan 2019 22:21:46 GMT")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rssDate2Test() {
|
||||||
|
val dateTime = LocalDateTime.of(2019, 1, 4, 22, 21, 46)
|
||||||
|
assertEquals(0, dateTime.compareTo(DateUtils.parse("Fri, 04 Jan 2019 22:21:46 +0000")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun rssDate3Test() {
|
||||||
|
val dateTime = LocalDateTime.of(2019, 1, 4, 22, 21, 46)
|
||||||
|
assertEquals(0, dateTime.compareTo(DateUtils.parse("Fri, 04 Jan 2019 22:21:46")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun edtPatternTest() {
|
||||||
|
val dateTime = LocalDateTime.of(2020, 7, 17, 16, 30, 0)
|
||||||
|
assertEquals(0, dateTime.compareTo(DateUtils.parse("Fri, 17 Jul 2020 16:30:00 EDT")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun atomJsonDateTest() {
|
||||||
|
val dateTime = LocalDateTime.of(2019, 1, 4, 22, 21, 46)
|
||||||
|
assertEquals(0, dateTime.compareTo(DateUtils.parse("2019-01-04T22:21:46+00:00")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun atomJsonDate2Test() {
|
||||||
|
val dateTime = LocalDateTime.of(2019, 1, 4, 22, 21, 46)
|
||||||
|
assertEquals(0, dateTime.compareTo(DateUtils.parse("2019-01-04T22:21:46-0000")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isoPatternTest() {
|
||||||
|
val dateTime = LocalDateTime.of(2020, 6, 30, 11, 39, 37, 206000000)
|
||||||
|
assertEquals(0, dateTime.compareTo(DateUtils.parse("2020-06-30T11:39:37.206-07:00")))
|
||||||
|
}
|
||||||
|
}
|
@ -42,8 +42,6 @@ dependencies {
|
|||||||
|
|
||||||
implementation(libs.bundles.paging)
|
implementation(libs.bundles.paging)
|
||||||
|
|
||||||
implementation(libs.jodatime)
|
|
||||||
|
|
||||||
implementation(libs.bundles.koin)
|
implementation(libs.bundles.koin)
|
||||||
testImplementation(libs.bundles.kointest)
|
testImplementation(libs.bundles.kointest)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import com.readrops.db.entities.Item
|
|||||||
import com.readrops.db.entities.ItemState
|
import com.readrops.db.entities.ItemState
|
||||||
import com.readrops.db.entities.ItemStateChange
|
import com.readrops.db.entities.ItemStateChange
|
||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
|
import com.readrops.db.util.Converters
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
entities = [Feed::class, Item::class, Folder::class, Account::class,
|
entities = [Feed::class, Item::class, Folder::class, Account::class,
|
||||||
|
@ -5,7 +5,7 @@ import androidx.room.Entity
|
|||||||
import androidx.room.ForeignKey
|
import androidx.room.ForeignKey
|
||||||
import androidx.room.Ignore
|
import androidx.room.Ignore
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import org.joda.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
foreignKeys = [
|
foreignKeys = [
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
package com.readrops.db
|
package com.readrops.db.util
|
||||||
|
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
import com.readrops.db.entities.account.AccountType
|
import com.readrops.db.entities.account.AccountType
|
||||||
import org.joda.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
class Converters {
|
class Converters {
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun fromTimeStamp(value: Long): LocalDateTime {
|
fun fromTimeStamp(value: Long): LocalDateTime {
|
||||||
return LocalDateTime(value)
|
return DateUtils.fromEpochSeconds(value / 1000L)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun fromLocalDateTime(localDateTime: LocalDateTime): Long {
|
fun fromLocalDateTime(localDateTime: LocalDateTime): Long {
|
||||||
return localDateTime.toDateTime().millis
|
return localDateTime.toInstant(DateUtils.defaultOffset).toEpochMilli()
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun fromAccountTypeCode(ordinal: Int): AccountType {
|
fun fromAccountTypeCode(ordinal: Int): AccountType {
|
||||||
return AccountType.values()[ordinal]
|
return AccountType.entries[ordinal]
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
102
db/src/main/java/com/readrops/db/util/DateUtils.kt
Normal file
102
db/src/main/java/com/readrops/db/util/DateUtils.kt
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package com.readrops.db.util
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.util.Log
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.OffsetDateTime
|
||||||
|
import java.time.ZoneOffset
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.format.DateTimeFormatterBuilder
|
||||||
|
import java.time.format.FormatStyle
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
|
|
||||||
|
object DateUtils {
|
||||||
|
|
||||||
|
private val TAG = DateUtils::class.java.simpleName
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base of common RSS 2 date formats.
|
||||||
|
* Examples :
|
||||||
|
* Fri, 04 Jan 2019 22:21:46 GMT
|
||||||
|
* Fri, 04 Jan 2019 22:21:46 +0000
|
||||||
|
*/
|
||||||
|
private const val RSS_2_BASE_PATTERN = "EEE, dd MMM yyyy HH:mm:ss"
|
||||||
|
|
||||||
|
private const val GMT_PATTERN = "ZZZ"
|
||||||
|
|
||||||
|
private const val OFFSET_PATTERN = "Z"
|
||||||
|
|
||||||
|
private const val ISO_PATTERN = ".SSSZZ"
|
||||||
|
|
||||||
|
private const val EDT_PATTERN = "zzz"
|
||||||
|
|
||||||
|
private const val ZONE_OFFSET_PATTERN = ".SSSxxx"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Date pattern for format : 2019-01-04T22:21:46+00:00
|
||||||
|
*/
|
||||||
|
private const val ATOM_JSON_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"
|
||||||
|
|
||||||
|
val defaultOffset: ZoneOffset
|
||||||
|
get() = OffsetDateTime.now(TimeZone.getDefault().toZoneId())
|
||||||
|
.offset
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to parse a date string representation.
|
||||||
|
* If the provided value is null or the parsing fails, [LocalDateTime.now] is returned.
|
||||||
|
* @return parsed date or [LocalDateTime.now]
|
||||||
|
*/
|
||||||
|
@SuppressLint("NewApi") // works with API 21+ so the lint might be buggy
|
||||||
|
@JvmStatic
|
||||||
|
fun parse(value: String?): LocalDateTime {
|
||||||
|
return if (value == null) {
|
||||||
|
LocalDateTime.now()
|
||||||
|
} else try {
|
||||||
|
val formatter = DateTimeFormatterBuilder()
|
||||||
|
.appendOptional(DateTimeFormatter.ofPattern("$RSS_2_BASE_PATTERN ")) // with timezone
|
||||||
|
.appendOptional(DateTimeFormatter.ofPattern(RSS_2_BASE_PATTERN)) // no timezone, important order here
|
||||||
|
.appendOptional(DateTimeFormatter.ofPattern(ATOM_JSON_DATE_FORMAT))
|
||||||
|
.appendOptional(DateTimeFormatter.ofPattern(EDT_PATTERN))
|
||||||
|
.appendOptional(DateTimeFormatter.ofPattern(ZONE_OFFSET_PATTERN))
|
||||||
|
.appendOptional(DateTimeFormatter.ofPattern(GMT_PATTERN))
|
||||||
|
.appendOptional(DateTimeFormatter.ofPattern(OFFSET_PATTERN))
|
||||||
|
.appendOptional(DateTimeFormatter.ofPattern(ISO_PATTERN))
|
||||||
|
.toFormatter()
|
||||||
|
.withLocale(Locale.ENGLISH)
|
||||||
|
|
||||||
|
LocalDateTime.from(formatter.parse(value))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.d(TAG, "Unable to parse $value: ${e.message}")
|
||||||
|
LocalDateTime.now()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Be aware of giving a second epoch value and not a millisecond one!
|
||||||
|
*/
|
||||||
|
fun fromEpochSeconds(epoch: Long): LocalDateTime {
|
||||||
|
return LocalDateTime.ofEpochSecond(
|
||||||
|
epoch,
|
||||||
|
0,
|
||||||
|
defaultOffset
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formattedDateByLocal(dateTime: LocalDateTime): String {
|
||||||
|
return DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
|
||||||
|
.withLocale(Locale.getDefault())
|
||||||
|
.format(dateTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun formattedDate(dateTime: LocalDateTime): String {
|
||||||
|
val pattern = if (dateTime.year != LocalDateTime.now().year) {
|
||||||
|
"dd MMMM yyyy"
|
||||||
|
} else {
|
||||||
|
"dd MMMM"
|
||||||
|
}
|
||||||
|
|
||||||
|
return DateTimeFormatter.ofPattern(pattern)
|
||||||
|
.format(dateTime)
|
||||||
|
}
|
||||||
|
}
|
@ -82,11 +82,10 @@ aboutlibraries-composem3 = { module = "com.mikepenz:aboutlibraries-compose-m3",
|
|||||||
konsumexml = "com.gitlab.mvysny.konsume-xml:konsume-xml:1.1"
|
konsumexml = "com.gitlab.mvysny.konsume-xml:konsume-xml:1.1"
|
||||||
kotlinxmlbuilder = "org.redundent:kotlin-xml-builder:1.7.3" #TODO update this
|
kotlinxmlbuilder = "org.redundent:kotlin-xml-builder:1.7.3" #TODO update this
|
||||||
|
|
||||||
jdk-desugar = "com.android.tools:desugar_jdk_libs:2.0.4"
|
jdk-desugar = "com.android.tools:desugar_jdk_libs_nio:2.0.4"
|
||||||
|
|
||||||
jsoup = "org.jsoup:jsoup:1.16.1"
|
jsoup = "org.jsoup:jsoup:1.16.1"
|
||||||
moshi = "com.squareup.moshi:moshi:1.15.1"
|
moshi = "com.squareup.moshi:moshi:1.15.1"
|
||||||
jodatime = "joda-time:joda-time:2.10.10" #TODO replace by java.time
|
|
||||||
|
|
||||||
# androidx
|
# androidx
|
||||||
corektx = "androidx.core:core-ktx:1.13.1"
|
corektx = "androidx.core:core-ktx:1.13.1"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user