NewPipeExtractor/extractor/src/main/java/org/schabi/newpipe/extractor/stream/TimeAgoParser.java

159 lines
5.4 KiB
Java
Raw Normal View History

package org.schabi.newpipe.extractor.stream;
/*
* Created by wojcik.online on 2018-01-25.
*/
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
/**
* A helper class that is meant to be used by services that need to parse upload dates in the
* format '2 days ago' or similar.
*/
public class TimeAgoParser {
/**
* A set of english phrases that are contained in the time units.
* (e.g. '7 minutes ago' contains 'min')
*/
public static Map<TimeAgoUnit, Collection<String>> DEFAULT_AGO_PHRASES =
new EnumMap<>(TimeAgoUnit.class);
private final Map<TimeAgoUnit, Collection<String>> agoPhrases;
private final Calendar consistentNow;
/**
* Creates a helper to parse upload dates in the format '2 days ago'.
* <p>
* Instantiate a new {@link TimeAgoParser} every time you extract a new batch of items.
* </p>
* @param agoPhrases A set of phrases how to recognize the time units in a given language.
*/
public TimeAgoParser(Map<TimeAgoUnit, Collection<String>> agoPhrases) {
this.agoPhrases = agoPhrases;
consistentNow = Calendar.getInstance();
}
/**
* Parses a textual date in the format '2 days ago' into a Calendar representation.
* Beginning with days ago, marks the date as approximated by setting minutes, seconds
* and milliseconds to 0.
* @param textualDate The original date as provided by the streaming service
* @return The parsed (approximated) time
* @throws ParsingException if the time unit could not be recognized
*/
public Calendar parse(String textualDate) throws ParsingException {
int timeAgoAmount;
try {
timeAgoAmount = parseTimeAgoAmount(textualDate);
} catch (NumberFormatException e) {
// If there is no valid number in the textual date,
// assume it is 1 (as in 'a second ago').
timeAgoAmount = 1;
}
TimeAgoUnit timeAgoUnit = parseTimeAgoUnit(textualDate);
return getCalendar(timeAgoAmount, timeAgoUnit);
}
private int parseTimeAgoAmount(String textualDate) throws NumberFormatException {
String timeValueStr = textualDate.replaceAll("\\D+", "");
return Integer.parseInt(timeValueStr);
}
private TimeAgoUnit parseTimeAgoUnit(String textualDate) throws ParsingException {
for (TimeAgoUnit timeAgoUnit : agoPhrases.keySet()) {
for (String agoPhrase : agoPhrases.get(timeAgoUnit)) {
if (textualDate.toLowerCase().contains(agoPhrase.toLowerCase())){
return timeAgoUnit;
}
}
}
throw new ParsingException("Unable to parse the date: " + textualDate);
}
private Calendar getCalendar(int timeAgoAmount, TimeAgoUnit timeAgoUnit) {
Calendar calendarTime = getNow();
switch (timeAgoUnit) {
case SECONDS:
calendarTime.add(Calendar.SECOND, -timeAgoAmount);
break;
case MINUTES:
calendarTime.add(Calendar.MINUTE, -timeAgoAmount);
break;
case HOURS:
calendarTime.add(Calendar.HOUR_OF_DAY, -timeAgoAmount);
break;
case DAYS:
calendarTime.add(Calendar.DAY_OF_MONTH, -timeAgoAmount);
markApproximatedTime(calendarTime);
break;
case WEEKS:
calendarTime.add(Calendar.WEEK_OF_YEAR, -timeAgoAmount);
markApproximatedTime(calendarTime);
break;
case MONTHS:
calendarTime.add(Calendar.MONTH, -timeAgoAmount);
markApproximatedTime(calendarTime);
break;
case YEARS:
calendarTime.add(Calendar.YEAR, -timeAgoAmount);
// Prevent `PrettyTime` from showing '12 months ago'.
calendarTime.add(Calendar.DAY_OF_MONTH, -1);
markApproximatedTime(calendarTime);
break;
}
return calendarTime;
}
private Calendar getNow() {
return (Calendar) consistentNow.clone();
}
/**
* Marks the time as approximated by setting minutes, seconds and milliseconds to 0.
* @param calendarTime Time to be marked as approximated
*/
private void markApproximatedTime(Calendar calendarTime) {
calendarTime.set(Calendar.MINUTE, 0);
calendarTime.set(Calendar.SECOND, 0);
calendarTime.set(Calendar.MILLISECOND, 0);
}
static {
DEFAULT_AGO_PHRASES.put(TimeAgoUnit.SECONDS, Collections.singleton("sec"));
DEFAULT_AGO_PHRASES.put(TimeAgoUnit.MINUTES, Collections.singleton("min"));
DEFAULT_AGO_PHRASES.put(TimeAgoUnit.HOURS, Collections.singleton("hour"));
DEFAULT_AGO_PHRASES.put(TimeAgoUnit.DAYS, Collections.singleton("day"));
DEFAULT_AGO_PHRASES.put(TimeAgoUnit.WEEKS, Collections.singleton("week"));
DEFAULT_AGO_PHRASES.put(TimeAgoUnit.MONTHS, Collections.singleton("month"));
DEFAULT_AGO_PHRASES.put(TimeAgoUnit.YEARS, Collections.singleton("year"));
}
public enum TimeAgoUnit {
SECONDS,
MINUTES,
HOURS,
DAYS,
WEEKS,
MONTHS,
YEARS,
}
}