mirror of https://github.com/readrops/Readrops.git
Revamp the way rss/atom/json dates are parsed and fix date tests
This commit is contained in:
parent
7aa0f94011
commit
272e867c8d
|
@ -120,7 +120,7 @@ public class ItemActivity extends AppCompatActivity {
|
|||
this.itemWithFeed = itemWithFeed;
|
||||
Item item = itemWithFeed.getItem();
|
||||
|
||||
date.setText(DateUtils.formatedDateTimeByLocal(item.getPubDate()));
|
||||
date.setText(DateUtils.formattedDateTimeByLocal(item.getPubDate()));
|
||||
|
||||
if (item.getImageLink() == null)
|
||||
toolbar.setTitle(itemWithFeed.getFeedName());
|
||||
|
|
|
@ -288,7 +288,7 @@ public class MainItemListAdapter extends PagedListAdapter<ItemWithFeed, MainItem
|
|||
Item item = itemWithFeed.getItem();
|
||||
|
||||
binding.itemTitle.setText(item.getTitle());
|
||||
binding.itemDate.setText(DateUtils.formatedDateByLocal(item.getPubDate()));
|
||||
binding.itemDate.setText(DateUtils.formattedDateByLocal(item.getPubDate()));
|
||||
binding.itemFeedName.setText(itemWithFeed.getFeedName());
|
||||
|
||||
if (item.getCleanDescription() != null) {
|
||||
|
|
|
@ -23,12 +23,12 @@ import com.readrops.readropslibrary.localfeed.atom.ATOMFeed;
|
|||
import com.readrops.readropslibrary.localfeed.json.JSONFeed;
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSFeed;
|
||||
import com.readrops.readropslibrary.utils.LibUtils;
|
||||
import com.readrops.readropslibrary.utils.ParseException;
|
||||
import com.readrops.readropslibrary.utils.UnknownFormatException;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
|
|
@ -1,36 +1,51 @@
|
|||
package com.readrops.app.utils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.joda.time.format.DateTimeFormatterBuilder;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public final class DateUtils {
|
||||
|
||||
public static final String RSS_ALTERNATIVE_DATE_FORMAT_REGEX = "^[a-zA-Z]{3}, [0-9]{2} [a-zA-Z]{3} [0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} Z$";
|
||||
/**
|
||||
* 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 static final String RSS_2_BASE_PATTERN = "EEE, dd MMM yyyy HH:mm:ss ";
|
||||
|
||||
public static final String RSS_2_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss Z";
|
||||
public static final String RSS_2_DATE_FORMAT_2 = "EEE, dd MMM yyyy HH:mm:ss z";
|
||||
public static final String RSS_2_DATE_FORMAT_3 = "EEE, dd MMM yyyy HH:mm:ss 'Z'";
|
||||
private static final String GMT_PATTERN = "ZZZ";
|
||||
|
||||
public static final String ATOM_JSON_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssX";
|
||||
private static final String OFFSET_PATTERN = "Z";
|
||||
|
||||
public static LocalDateTime stringToDateTime(String value, String pattern) throws ParseException {
|
||||
DateFormat formatter = new SimpleDateFormat(pattern, Locale.ENGLISH);
|
||||
return new LocalDateTime(formatter.parse(value));
|
||||
/**
|
||||
* Date pattern for format : 2019-01-04T22:21:46+00:00
|
||||
*/
|
||||
private static final String ATOM_JSON_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
|
||||
|
||||
public static LocalDateTime stringToLocalDateTime(String value) {
|
||||
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
|
||||
.appendOptional(DateTimeFormat.forPattern(RSS_2_BASE_PATTERN).getParser())
|
||||
.appendOptional(DateTimeFormat.forPattern(ATOM_JSON_DATE_FORMAT).getParser())
|
||||
.appendOptional(DateTimeFormat.forPattern(GMT_PATTERN).getParser())
|
||||
.appendOptional(DateTimeFormat.forPattern(OFFSET_PATTERN).getParser())
|
||||
.toFormatter()
|
||||
.withLocale(Locale.ENGLISH)
|
||||
.withOffsetParsed();
|
||||
|
||||
return formatter.parseLocalDateTime(value);
|
||||
}
|
||||
|
||||
public static String formatedDateByLocal(LocalDateTime dateTime) {
|
||||
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault());
|
||||
|
||||
return df.format(dateTime.toDate());
|
||||
public static String formattedDateByLocal(LocalDateTime dateTime) {
|
||||
return DateTimeFormat.mediumDate()
|
||||
.withLocale(Locale.getDefault())
|
||||
.print(dateTime);
|
||||
}
|
||||
|
||||
public static String formatedDateTimeByLocal(LocalDateTime dateTime) {
|
||||
public static String formattedDateTimeByLocal(LocalDateTime dateTime) {
|
||||
return DateTimeFormat.forPattern("dd MMM yyyy · HH:mm")
|
||||
.withLocale(Locale.getDefault())
|
||||
.print(dateTime);
|
||||
|
|
|
@ -9,15 +9,14 @@ import com.readrops.readropslibrary.localfeed.rss.RSSItem;
|
|||
import com.readrops.readropslibrary.localfeed.rss.RSSMediaContent;
|
||||
import com.readrops.readropslibrary.services.freshrss.json.FreshRSSItem;
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItem;
|
||||
import com.readrops.readropslibrary.utils.ParseException;
|
||||
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.jsoup.Jsoup;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class ItemMatcher {
|
||||
|
||||
|
@ -75,31 +74,16 @@ public final class ItemMatcher {
|
|||
newItem.setGuid(item.getGuid());
|
||||
newItem.setTitle(Jsoup.parse(item.getTitle()).text().trim());
|
||||
|
||||
// I wish I hadn't done that...
|
||||
if (Pattern.compile(DateUtils.RSS_ALTERNATIVE_DATE_FORMAT_REGEX).matcher(item.getDate()).matches())
|
||||
newItem.setPubDate(DateUtils.stringToDateTime(item.getDate(), DateUtils.RSS_2_DATE_FORMAT_3));
|
||||
else {
|
||||
try {
|
||||
newItem.setPubDate(DateUtils.stringToDateTime(item.getDate(), DateUtils.RSS_2_DATE_FORMAT_2));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (newItem.getPubDate() == null) {
|
||||
try {
|
||||
newItem.setPubDate(DateUtils.stringToDateTime(item.getDate(), DateUtils.RSS_2_DATE_FORMAT));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
newItem.setPubDate(DateUtils.stringToDateTime(item.getDate(), DateUtils.ATOM_JSON_DATE_FORMAT));
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
newItem.setPubDate(DateUtils.stringToLocalDateTime(item.getDate()));
|
||||
} catch (Exception e) {
|
||||
throw new ParseException();
|
||||
}
|
||||
|
||||
newItem.setLink(item.getLink());
|
||||
newItem.setFeedId(feed.getId());
|
||||
|
||||
if (item.getMediaContents() != null && item.getMediaContents().size() > 0) {
|
||||
if (item.getMediaContents() != null && !item.getMediaContents().isEmpty()) {
|
||||
for (RSSMediaContent mediaContent : item.getMediaContents()) {
|
||||
if (mediaContent.getMedium() != null && Utils.isTypeImage(mediaContent.getMedium())) {
|
||||
newItem.setImageLink(mediaContent.getUrl());
|
||||
|
@ -135,7 +119,11 @@ public final class ItemMatcher {
|
|||
dbItem.setGuid(item.getId());
|
||||
dbItem.setTitle(Jsoup.parse(item.getTitle()).text().trim());
|
||||
|
||||
dbItem.setPubDate(DateUtils.stringToDateTime(item.getUpdated(), DateUtils.ATOM_JSON_DATE_FORMAT));
|
||||
try {
|
||||
dbItem.setPubDate(DateUtils.stringToLocalDateTime(item.getUpdated()));
|
||||
} catch (Exception e) {
|
||||
throw new ParseException();
|
||||
}
|
||||
dbItem.setLink(item.getUrl());
|
||||
|
||||
dbItem.setFeedId(feed.getId());
|
||||
|
@ -160,7 +148,11 @@ public final class ItemMatcher {
|
|||
dbItem.setGuid(item.getId());
|
||||
dbItem.setTitle(Jsoup.parse(item.getTitle()).text().trim());
|
||||
|
||||
dbItem.setPubDate(DateUtils.stringToDateTime(item.getPubDate(), DateUtils.ATOM_JSON_DATE_FORMAT));
|
||||
try {
|
||||
dbItem.setPubDate(DateUtils.stringToLocalDateTime(item.getPubDate()));
|
||||
} catch (Exception e) {
|
||||
throw new ParseException();
|
||||
}
|
||||
|
||||
dbItem.setLink(item.getUrl());
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package com.readrops.app;
|
||||
|
||||
import com.readrops.app.utils.DateUtils;
|
||||
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class DateUtilsTest {
|
||||
|
||||
@Test
|
||||
public void rssDateTest() {
|
||||
LocalDateTime dateTime = new LocalDateTime(2019, 1, 4, 22, 21, 46);
|
||||
|
||||
assertEquals(0, dateTime.compareTo(DateUtils.stringToLocalDateTime("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.stringToLocalDateTime("Fri, 04 Jan 2019 22:21:46 +0000")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atomJsonDateTest() {
|
||||
LocalDateTime dateTime = new LocalDateTime(2019, 1, 4, 22, 21, 46);
|
||||
|
||||
assertEquals(0, dateTime.compareTo(DateUtils.stringToLocalDateTime("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.stringToLocalDateTime("2019-01-04T22:21:46-0000")));
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package com.readrops.app;
|
||||
|
||||
import com.readrops.app.utils.DateUtils;
|
||||
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
|
||||
@Test
|
||||
public void rssDateTest() {
|
||||
try {
|
||||
LocalDateTime dateTime = new LocalDateTime(2019, 1, 4, 22, 21, 46);
|
||||
|
||||
assertEquals(0, dateTime.compareTo(DateUtils.stringToDateTime("Fri, 04 Jan 2019 22:21:46 +0000", DateUtils.RSS_2_DATE_FORMAT)));
|
||||
assertEquals(0, dateTime.compareTo(DateUtils.stringToDateTime("Fri, 04 Jan 2019 22:21:46 GMT", DateUtils.RSS_2_DATE_FORMAT_2)));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atomJsonDateTest() {
|
||||
try {
|
||||
LocalDateTime dateTime = new LocalDateTime(2019, 1, 4, 22, 21, 46);
|
||||
|
||||
assertEquals(0, dateTime.compareTo(DateUtils.stringToDateTime("2019-01-04T22:21:46+00:00", DateUtils.ATOM_JSON_DATE_FORMAT)));
|
||||
assertEquals(0, dateTime.compareTo(DateUtils.stringToDateTime("2019-01-04T22:21:46-0000", DateUtils.ATOM_JSON_DATE_FORMAT)));
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timeStamptoDateTest() {
|
||||
LocalDateTime localDateTime = new LocalDateTime(1367270544 * 1000L, DateTimeZone.getDefault());
|
||||
|
||||
assertEquals(0, localDateTime.compareTo(new LocalDateTime(2013, 4, 29, 21, 22, 24)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.readrops.readropslibrary.utils;
|
||||
|
||||
public class ParseException extends Exception {
|
||||
|
||||
}
|
Loading…
Reference in New Issue