diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java b/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java index 26e84da97..c613d34f2 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/StreamingService.java @@ -17,6 +17,7 @@ import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandlerFactory; import org.schabi.newpipe.extractor.playlist.PlaylistExtractor; import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.stream.StreamExtractor; +import org.schabi.newpipe.extractor.stream.TimeAgoParser; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; import org.schabi.newpipe.extractor.utils.Localization; @@ -222,7 +223,7 @@ public abstract class StreamingService { public ChannelExtractor getChannelExtractor(ListLinkHandler linkHandler) throws ExtractionException { return getChannelExtractor(linkHandler, NewPipe.getPreferredLocalization()); } - + public PlaylistExtractor getPlaylistExtractor(ListLinkHandler linkHandler) throws ExtractionException { return getPlaylistExtractor(linkHandler, NewPipe.getPreferredLocalization()); } @@ -230,7 +231,7 @@ public abstract class StreamingService { public StreamExtractor getStreamExtractor(LinkHandler linkHandler) throws ExtractionException { return getStreamExtractor(linkHandler, NewPipe.getPreferredLocalization()); } - + public CommentsExtractor getCommentsExtractor(ListLinkHandler urlIdHandler) throws ExtractionException { return getCommentsExtractor(urlIdHandler, NewPipe.getPreferredLocalization()); } @@ -287,7 +288,7 @@ public abstract class StreamingService { public StreamExtractor getStreamExtractor(String url) throws ExtractionException { return getStreamExtractor(getStreamLHFactory().fromUrl(url), NewPipe.getPreferredLocalization()); } - + public CommentsExtractor getCommentsExtractor(String url) throws ExtractionException { ListLinkHandlerFactory llhf = getCommentsLHFactory(); if(null == llhf) { @@ -296,6 +297,9 @@ public abstract class StreamingService { return getCommentsExtractor(llhf.fromUrl(url), NewPipe.getPreferredLocalization()); } + public TimeAgoParser getTimeAgoParser() { + return new TimeAgoParser(TimeAgoParser.DEFAULT_AGO_PHRASES); + } /** * Figures out where the link is pointing to (a channel, a video, a playlist, etc.) diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java index 96b7fcea7..d4a8123c0 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudParsingHelper.java @@ -79,23 +79,22 @@ public class SoundcloudParsingHelper { return dl.head(apiUrl).getResponseCode() == 200; } - public static String toDateString(String time) throws ParsingException { + static Date parseDate(String time) throws ParsingException { try { - Date date; - // Have two date formats, one for the 'api.soundc...' and the other 'api-v2.soundc...'. + return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(time); + } catch (ParseException e1) { try { - date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(time); - } catch (Exception e) { - date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse(time); + return new SimpleDateFormat("yyyy/MM/dd HH:mm:ss +0000").parse(time); + } catch (ParseException e2) { + throw new ParsingException(e1.getMessage(), e2); } - - SimpleDateFormat newDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - return newDateFormat.format(date); - } catch (ParseException e) { - throw new ParsingException(e.getMessage(), e); } } + static String toTextualDate(String time) throws ParsingException { + return new SimpleDateFormat("yyyy-MM-dd").format(parseDate(time)); + } + /** * Call the endpoint "/resolve" of the api.
*
diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java
index f5860d835..b842d85af 100644
--- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java
+++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamExtractor.java
@@ -51,7 +51,7 @@ public class SoundcloudStreamExtractor extends StreamExtractor {
@Nonnull
@Override
public String getUploadDate() throws ParsingException {
- return SoundcloudParsingHelper.toDateString(track.getString("created_at"));
+ return SoundcloudParsingHelper.toTextualDate(track.getString("created_at"));
}
@Nonnull
diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java
index 09455e193..a81421f01 100644
--- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java
+++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/soundcloud/SoundcloudStreamInfoItemExtractor.java
@@ -5,6 +5,8 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
import org.schabi.newpipe.extractor.stream.StreamType;
+import java.util.Calendar;
+
import static org.schabi.newpipe.extractor.utils.Utils.replaceHttpWithHttps;
public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtractor {
@@ -41,8 +43,19 @@ public class SoundcloudStreamInfoItemExtractor implements StreamInfoItemExtracto
}
@Override
- public String getUploadDate() throws ParsingException {
- return SoundcloudParsingHelper.toDateString(itemObject.getString("created_at"));
+ public String getTextualUploadDate() throws ParsingException {
+ return SoundcloudParsingHelper.toTextualDate(getCreatedAt());
+ }
+
+ @Override
+ public Calendar getUploadDate() throws ParsingException {
+ Calendar uploadTime = Calendar.getInstance();
+ uploadTime.setTime(SoundcloudParsingHelper.parseDate(getCreatedAt()));
+ return uploadTime;
+ }
+
+ private String getCreatedAt() {
+ return itemObject.getString("created_at");
}
@Override
diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java
index 9641d3931..14c5a9ed1 100644
--- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java
+++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeChannelExtractor.java
@@ -18,6 +18,7 @@ import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
+import org.schabi.newpipe.extractor.stream.TimeAgoParser;
import org.schabi.newpipe.extractor.utils.DonationLinkHelper;
import org.schabi.newpipe.extractor.utils.Localization;
import org.schabi.newpipe.extractor.utils.Parser;
@@ -53,6 +54,8 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
private static final String CHANNEL_FEED_BASE = "https://www.youtube.com/feeds/videos.xml?channel_id=";
private static final String CHANNEL_URL_PARAMETERS = "/videos?view=0&flow=list&sort=dd&live_view=10000&gl=US&hl=en";
+ private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser();
+
private Document doc;
public YoutubeChannelExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) {
@@ -230,7 +233,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
final String uploaderUrl = getUrl();
for (final Element li : element.children()) {
if (li.select("div[class=\"feed-item-dismissable\"]").first() != null) {
- collector.commit(new YoutubeStreamInfoItemExtractor(li) {
+ collector.commit(new YoutubeStreamInfoItemExtractor(li, timeAgoParser) {
@Override
public String getUrl() throws ParsingException {
try {
diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java
index 4480b38af..0d5668e9f 100644
--- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java
+++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubePlaylistExtractor.java
@@ -18,6 +18,7 @@ import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingH
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.stream.StreamInfoItemsCollector;
import org.schabi.newpipe.extractor.stream.StreamType;
+import org.schabi.newpipe.extractor.stream.TimeAgoParser;
import org.schabi.newpipe.extractor.utils.Localization;
import org.schabi.newpipe.extractor.utils.Utils;
@@ -28,6 +29,8 @@ import java.io.IOException;
@SuppressWarnings("WeakerAccess")
public class YoutubePlaylistExtractor extends PlaylistExtractor {
+ private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser();
+
private Document doc;
public YoutubePlaylistExtractor(StreamingService service, ListLinkHandler linkHandler, Localization localization) {
@@ -192,7 +195,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
continue;
}
- collector.commit(new YoutubeStreamInfoItemExtractor(li) {
+ collector.commit(new YoutubeStreamInfoItemExtractor(li, timeAgoParser) {
public Element uploaderLink;
@Override
@@ -258,7 +261,7 @@ public class YoutubePlaylistExtractor extends PlaylistExtractor {
}
@Override
- public String getUploadDate() throws ParsingException {
+ public String getTextualUploadDate() throws ParsingException {
return "";
}
diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java
index 0a954607f..c3f234aaf 100644
--- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java
+++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeSearchExtractor.java
@@ -9,6 +9,7 @@ import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
+import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
import org.schabi.newpipe.extractor.search.InfoItemsSearchCollector;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
@@ -129,7 +130,7 @@ public class YoutubeSearchExtractor extends SearchExtractor {
// video item type
} else if ((el = item.select("div[class*=\"yt-lockup-video\"]").first()) != null) {
- collector.commit(new YoutubeStreamInfoItemExtractor(el));
+ collector.commit(new YoutubeStreamInfoItemExtractor(el, getService().getTimeAgoParser()));
} else if ((el = item.select("div[class*=\"yt-lockup-channel\"]").first()) != null) {
collector.commit(new YoutubeChannelInfoItemExtractor(el));
} else if ((el = item.select("div[class*=\"yt-lockup-playlist\"]").first()) != null &&
diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java
index fa866cd5b..4c33a258c 100644
--- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java
+++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamExtractor.java
@@ -75,6 +75,8 @@ public class YoutubeStreamExtractor extends StreamExtractor {
/*//////////////////////////////////////////////////////////////////////////*/
+ private final TimeAgoParser timeAgoParser = getService().getTimeAgoParser();
+
private Document doc;
@Nullable
private JsonObject playerArgs;
@@ -932,7 +934,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
* This is encapsulated in a StreamInfoItem object, which is a subset of the fields in a full StreamInfo.
*/
private StreamInfoItemExtractor extractVideoPreviewInfo(final Element li) {
- return new YoutubeStreamInfoItemExtractor(li) {
+ return new YoutubeStreamInfoItemExtractor(li, timeAgoParser) {
@Override
public String getUrl() throws ParsingException {
@@ -959,7 +961,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
}
@Override
- public String getUploadDate() throws ParsingException {
+ public String getTextualUploadDate() throws ParsingException {
return "";
}
diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java
index 5bfeaa38e..763c25380 100644
--- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java
+++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeStreamInfoItemExtractor.java
@@ -1,12 +1,17 @@
package org.schabi.newpipe.extractor.services.youtube.extractors;
import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.stream.StreamInfoItemExtractor;
import org.schabi.newpipe.extractor.stream.StreamType;
+import org.schabi.newpipe.extractor.stream.TimeAgoParser;
import org.schabi.newpipe.extractor.utils.Utils;
+import javax.annotation.Nullable;
+import java.util.Calendar;
+
/*
* Copyright (C) Christian Schabesberger 2016
+ * If the service doesn't provide an exact time, an approximation can be returned.
+ * The approximation should be marked by setting seconds and milliseconds to zero.
+ *
+ * Instantiate a new {@link TimeAgoParser} every time you extract a new batch of items.
+ *
+ * If the service doesn't provide any date at all, then {@code null} should be returned.
+ *