diff --git a/app/src/main/java/com/hippo/ehviewer/client/parser/GalleryDetailParser.java b/app/src/main/java/com/hippo/ehviewer/client/parser/GalleryDetailParser.java
index fc6b453c7..5eb09494b 100644
--- a/app/src/main/java/com/hippo/ehviewer/client/parser/GalleryDetailParser.java
+++ b/app/src/main/java/com/hippo/ehviewer/client/parser/GalleryDetailParser.java
@@ -46,14 +46,12 @@ import org.jsoup.select.Elements;
import org.jsoup.select.NodeTraversor;
import org.jsoup.select.NodeVisitor;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
-import java.util.Date;
-import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
-import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -64,9 +62,6 @@ public class GalleryDetailParser {
private static final Pattern PATTERN_TORRENT = Pattern.compile("]*onclick=\"return popUp\\('([^']+)'[^)]+\\)\">Torrent Download[^<]+(\\d+)[^<]+]*onclick=\"return popUp\\('([^']+)'[^)]+\\)\">Archive Download");
private static final Pattern PATTERN_COVER = Pattern.compile("width:(\\d+)px; height:(\\d+)px.+?url\\((.+?)\\)");
- private static final Pattern PATTERN_TAG_GROUP = Pattern.compile("
| ]+>([\\w\\s]+): | (?:)+ |
");
- private static final Pattern PATTERN_TAG = Pattern.compile("");
- private static final Pattern PATTERN_COMMENT = Pattern.compile("Posted on ([^<>]+) by:
]+>([^<>]+).+?
]*>(.+?)
| ]*>Length: | ]*>([\\d,]+) pages | ");
private static final Pattern PATTERN_PREVIEW_PAGES = Pattern.compile("
]+>]+>([\\d,]+) | ]+>(?:]+>)?>(?:)? | ");
private static final Pattern PATTERN_NORMAL_PREVIEW = Pattern.compile("
]*>
]*width:(\\d+)[^<>]*height:(\\d+)[^<>]*\\((.+?)\\)[^<>]*-(\\d+)px[^<>]*>
]*href=\"(.+?)\"[^<>]*>
gd.favoriteCount = 0;
+ case "Once" -> gd.favoriteCount = 1;
+ default -> {
int index = value.indexOf(' ');
if (index == -1) {
gd.favoriteCount = 0;
} else {
gd.favoriteCount = NumberUtils.parseIntSafely(value.substring(0, index), 0);
}
- break;
+ }
}
}
}
@@ -375,6 +362,7 @@ public class GalleryDetailParser {
public static GalleryTagGroup[] parseTagGroups(Document document) {
try {
Element taglist = document.getElementById("taglist");
+ assert taglist != null;
Elements tagGroups = taglist.child(0).child(0).children();
return parseTagGroups(tagGroups);
} catch (Throwable e) {
@@ -394,7 +382,7 @@ public class GalleryDetailParser {
list.add(group);
}
}
- return list.toArray(new GalleryTagGroup[list.size()]);
+ return list.toArray(new GalleryTagGroup[0]);
} catch (Throwable e) {
ExceptionUtils.throwIfFatal(e);
e.printStackTrace();
@@ -402,31 +390,6 @@ public class GalleryDetailParser {
}
}
- /**
- * Parse tag groups with regular expressions
- */
- @NonNull
- private static GalleryTagGroup[] parseTagGroups(String body) throws EhException {
- List list = new LinkedList<>();
-
- Matcher m = PATTERN_TAG_GROUP.matcher(body);
- while (m.find()) {
- GalleryTagGroup tagGroup = new GalleryTagGroup();
- tagGroup.groupName = ParserUtils.trim(m.group(1));
- parseGroup(tagGroup, m.group(0));
- list.add(tagGroup);
- }
-
- return list.toArray(new GalleryTagGroup[list.size()]);
- }
-
- private static void parseGroup(GalleryTagGroup tagGroup, String body) {
- Matcher m = PATTERN_TAG.matcher(body);
- while (m.find()) {
- tagGroup.addTag(ParserUtils.trim(m.group(1)));
- }
- }
-
@Nullable
@SuppressWarnings("ConstantConditions")
public static GalleryComment parseComment(Element element) {
@@ -444,17 +407,15 @@ public class GalleryDetailParser {
}
for (Element e : c4.children()) {
switch (e.text()) {
- case "Vote+":
+ case "Vote+" -> {
comment.voteUpAble = true;
comment.voteUpEd = !StringUtils.trim(e.attr("style")).isEmpty();
- break;
- case "Vote-":
+ }
+ case "Vote-" -> {
comment.voteDownAble = true;
comment.voteDownEd = !StringUtils.trim(e.attr("style")).isEmpty();
- break;
- case "Edit":
- comment.editable = true;
- break;
+ }
+ case "Edit" -> comment.editable = true;
}
}
}
@@ -475,7 +436,7 @@ public class GalleryDetailParser {
Element c3 = JsoupUtils.getElementByClass(element, "c3");
String temp = c3.ownText();
temp = temp.substring("Posted on ".length(), temp.length() - " by:".length());
- comment.time = WEB_COMMENT_DATE_FORMAT.parse(temp).getTime();
+ comment.time = Instant.from(WEB_COMMENT_DATE_FORMAT.parse(temp)).toEpochMilli();
// user
comment.user = c3.child(0).text();
// comment
@@ -485,7 +446,7 @@ public class GalleryDetailParser {
if (c8 != null) {
Element e = c8.children().first();
if (e != null) {
- comment.lastEdited = WEB_COMMENT_DATE_FORMAT.parse(temp).getTime();
+ comment.lastEdited = Instant.from(WEB_COMMENT_DATE_FORMAT.parse(temp)).toEpochMilli();
}
}
return comment;
@@ -503,6 +464,7 @@ public class GalleryDetailParser {
public static GalleryCommentList parseComments(Document document) {
try {
Element cdiv = document.getElementById("cdiv");
+ assert cdiv != null;
Elements c1s = cdiv.getElementsByClass("c1");
List list = new ArrayList<>(c1s.size());
@@ -515,20 +477,21 @@ public class GalleryDetailParser {
Element chd = cdiv.getElementById("chd");
MutableBoolean hasMore = new MutableBoolean(false);
+ assert chd != null;
NodeTraversor.traverse(new NodeVisitor() {
@Override
- public void head(Node node, int depth) {
+ public void head(@NonNull Node node, int depth) {
if (node instanceof Element && ((Element) node).text().equals("click to show all")) {
hasMore.value = true;
}
}
@Override
- public void tail(Node node, int depth) {
+ public void tail(@NonNull Node node, int depth) {
}
}, chd);
- return new GalleryCommentList(list.toArray(new GalleryComment[list.size()]), hasMore.value);
+ return new GalleryCommentList(list.toArray(new GalleryComment[0]), hasMore.value);
} catch (Throwable e) {
ExceptionUtils.throwIfFatal(e);
e.printStackTrace();
@@ -536,38 +499,14 @@ public class GalleryDetailParser {
}
}
- /**
- * Parse comments with regular expressions
- */
- @NonNull
- public static GalleryComment[] parseComments(String body) {
- List list = new LinkedList<>();
-
- Matcher m = PATTERN_COMMENT.matcher(body);
- while (m.find()) {
- String webDateString = ParserUtils.trim(m.group(1));
- Date date;
- try {
- date = WEB_COMMENT_DATE_FORMAT.parse(webDateString);
- } catch (java.text.ParseException e) {
- date = new Date(0L);
- }
- GalleryComment comment = new GalleryComment();
- comment.time = date.getTime();
- comment.user = ParserUtils.trim(m.group(2));
- comment.comment = m.group(3);
- list.add(comment);
- }
-
- return list.toArray(new GalleryComment[list.size()]);
- }
-
/**
* Parse preview pages with html parser
*/
public static int parsePreviewPages(Document document, String body) throws ParseException {
try {
- Elements elements = document.getElementsByClass("ptt").first().child(0).child(0).children();
+ Element ptt = document.getElementsByClass("ptt").first();
+ assert ptt != null;
+ Elements elements = ptt.child(0).child(0).children();
return Integer.parseInt(elements.get(elements.size() - 2).text());
} catch (Throwable e) {
ExceptionUtils.throwIfFatal(e);
@@ -634,9 +573,10 @@ public class GalleryDetailParser {
try {
LargePreviewSet largePreviewSet = new LargePreviewSet();
Element gdt = d.getElementById("gdt");
+ assert gdt != null;
Elements gdtls = gdt.getElementsByClass("gdtl");
int n = gdtls.size();
- if (n <= 0) {
+ if (n == 0) {
throw new ParseException("Can't parse large preview", body);
}
for (int i = 0; i < n; i++) {
diff --git a/app/src/main/java/com/hippo/ehviewer/client/parser/ParserUtils.java b/app/src/main/java/com/hippo/ehviewer/client/parser/ParserUtils.java
index 19f48294c..33d2ce100 100644
--- a/app/src/main/java/com/hippo/ehviewer/client/parser/ParserUtils.java
+++ b/app/src/main/java/com/hippo/ehviewer/client/parser/ParserUtils.java
@@ -19,19 +19,18 @@ package com.hippo.ehviewer.client.parser;
import com.hippo.yorozuya.NumberUtils;
import com.hippo.yorozuya.StringUtils;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import java.util.Locale;
-import java.util.TimeZone;
public class ParserUtils {
- public static final DateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
+ public static final DateTimeFormatter formatter = DateTimeFormatter
+ .ofPattern("yyyy-MM-dd HH:mm", Locale.US).withZone(ZoneOffset.UTC);
public static synchronized String formatDate(long time) {
- sDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
- return sDateFormat.format(new Date(time));
+ return formatter.format(Instant.ofEpochMilli(time));
}
public static String trim(String str) {
@@ -50,7 +49,4 @@ public class ParserUtils {
return NumberUtils.parseLongSafely(trim(str).replace(",", ""), defValue);
}
- public static float parseFloat(String str, float defValue) {
- return NumberUtils.parseFloatSafely(trim(str).replace(",", ""), defValue);
- }
}
diff --git a/app/src/main/java/com/hippo/ehviewer/widget/GalleryInfoContentHelper.kt b/app/src/main/java/com/hippo/ehviewer/widget/GalleryInfoContentHelper.kt
index abad4a399..2b7c33612 100644
--- a/app/src/main/java/com/hippo/ehviewer/widget/GalleryInfoContentHelper.kt
+++ b/app/src/main/java/com/hippo/ehviewer/widget/GalleryInfoContentHelper.kt
@@ -16,8 +16,6 @@
package com.hippo.ehviewer.widget
import android.annotation.SuppressLint
-import android.icu.text.SimpleDateFormat
-import android.icu.util.Calendar
import android.os.Bundle
import android.os.Parcelable
import com.hippo.ehviewer.EhApplication
@@ -25,7 +23,12 @@ import com.hippo.ehviewer.FavouriteStatusRouter
import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.widget.ContentLayout.ContentHelper
import com.hippo.yorozuya.IntIdGenerator
+import java.time.Instant
+import java.time.ZoneOffset
+import java.time.format.DateTimeFormatter
import java.util.Locale
+import kotlin.math.max
+import kotlin.math.min
abstract class GalleryInfoContentHelper : ContentHelper() {
@JvmField
@@ -64,8 +67,8 @@ abstract class GalleryInfoContentHelper : ContentHelper() {
info?.let {
if (maxGid == -1) maxGid = info.gid.toInt()
if (minGid == -1) minGid = info.gid.toInt()
- maxGid = Math.max(maxGid.toLong(), info.gid).toInt()
- minGid = Math.min(minGid.toLong(), info.gid).toInt()
+ maxGid = max(maxGid.toLong(), info.gid).toInt()
+ minGid = min(minGid.toLong(), info.gid).toInt()
map[info.gid] = info
}
}
@@ -121,11 +124,9 @@ abstract class GalleryInfoContentHelper : ContentHelper() {
}
fun goTo(time: Long) {
- val calendar = Calendar.getInstance()
- calendar.timeInMillis = time
- val date = calendar.time
- val format = SimpleDateFormat("yyyy-MM-dd", Locale.US)
- jumpTo = format.format(date)
+ val formatter = DateTimeFormatter
+ .ofPattern("yyyy-MM-dd", Locale.US).withZone(ZoneOffset.UTC)
+ jumpTo = formatter.format(Instant.ofEpochMilli(time))
doGoToPage(Int.MAX_VALUE / 2)
}
diff --git a/app/src/main/java/com/hippo/util/ReadableTime.java b/app/src/main/java/com/hippo/util/ReadableTime.java
index 64fe3b79c..c4679240a 100644
--- a/app/src/main/java/com/hippo/util/ReadableTime.java
+++ b/app/src/main/java/com/hippo/util/ReadableTime.java
@@ -16,18 +16,17 @@
package com.hippo.util;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import com.hippo.ehviewer.R;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import java.util.Locale;
-@SuppressLint("SimpleDateFormat")
public final class ReadableTime {
public static final long SECOND_MILLIS = 1000;
@@ -51,38 +50,19 @@ public final class ReadableTime {
R.plurals.minute,
R.plurals.second
};
- private static final Calendar sCalendar = Calendar.getInstance();
private static final Object sCalendarLock = new Object();
- private static final SimpleDateFormat DATE_FORMAT_WITHOUT_YEAR = new SimpleDateFormat("MMM d");
- private static final SimpleDateFormat DATE_FORMAT_WITH_YEAR = new SimpleDateFormat("MMM d, yyyy");
- private static final SimpleDateFormat DATE_FORMAT_WITHOUT_YEAR_ZH = new SimpleDateFormat("M月d日");
- private static final SimpleDateFormat DATE_FORMAT_WITH_YEAR_ZH = new SimpleDateFormat("yyyy年M月d日");
- private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yy-MM-dd HH:mm");
- private static final Object sDateFormatLock1 = new Object();
- private static final SimpleDateFormat FILENAMABLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");
- private static final Object sDateFormatLock2 = new Object();
+ private static final DateTimeFormatter DATE_FORMAT_WITHOUT_YEAR = DateTimeFormatter.ofPattern("MMM d");
+ private static final DateTimeFormatter DATE_FORMAT_WITH_YEAR = DateTimeFormatter.ofPattern("MMM d, yyyy");
+ private static final DateTimeFormatter DATE_FORMAT_WITHOUT_YEAR_ZH = DateTimeFormatter.ofPattern("M月d日");
+ private static final DateTimeFormatter DATE_FORMAT_WITH_YEAR_ZH = DateTimeFormatter.ofPattern("yyyy年M月d日");
+ private static final DateTimeFormatter FILENAMABLE_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss-SSS");
+ private static final Object sDateFormatLock = new Object();
private static Resources sResources;
public static void initialize(Context context) {
sResources = context.getApplicationContext().getResources();
}
- /*
- public static String getDisplayTime(long time) {
- if (Settings.getPrettyTime()) {
- return getTimeAgo(time);
- } else {
- return getPlainTime(time);
- }
- }
- */
-
- public static String getPlainTime(long time) {
- synchronized (sDateFormatLock1) {
- return DATE_FORMAT.format(new Date(time));
- }
- }
-
public static String getTimeAgo(long time) {
Resources resources = sResources;
@@ -111,49 +91,23 @@ public final class ReadableTime {
return resources.getString(R.string.some_days_ago, days);
} else {
synchronized (sCalendarLock) {
- Date nowDate = new Date(now);
- Date timeDate = new Date(time);
- sCalendar.setTime(nowDate);
- int nowYear = sCalendar.get(Calendar.YEAR);
- sCalendar.setTime(timeDate);
- int timeYear = sCalendar.get(Calendar.YEAR);
+ OffsetDateTime nowDate = Instant.ofEpochMilli(now).atOffset(ZoneOffset.UTC);
+ OffsetDateTime timeDate = Instant.ofEpochMilli(time).atOffset(ZoneOffset.UTC);
+ int nowYear = nowDate.getYear();
+ int timeYear = timeDate.getYear();
boolean isZh = Locale.getDefault().getLanguage().equals("zh");
if (nowYear == timeYear) {
- return (isZh ? DATE_FORMAT_WITHOUT_YEAR_ZH : DATE_FORMAT_WITHOUT_YEAR).format(timeDate);
+ return (isZh ? DATE_FORMAT_WITHOUT_YEAR_ZH : DATE_FORMAT_WITHOUT_YEAR)
+ .format(timeDate.toInstant().atOffset(ZoneOffset.UTC));
} else {
- return (isZh ? DATE_FORMAT_WITH_YEAR_ZH : DATE_FORMAT_WITH_YEAR).format(timeDate);
+ return (isZh ? DATE_FORMAT_WITH_YEAR_ZH : DATE_FORMAT_WITH_YEAR)
+ .format(timeDate.toInstant().atOffset(ZoneOffset.UTC));
}
}
}
}
- public static String getTimeInterval(long time) {
- StringBuilder sb = new StringBuilder();
- Resources resources = sResources;
-
- long leftover = time;
- boolean start = false;
-
- for (int i = 0; i < SIZE; i++) {
- long multiple = MULTIPLES[i];
- long quotient = leftover / multiple;
- long remainder = leftover % multiple;
- if (start || quotient != 0 || i == SIZE - 1) {
- if (start) {
- sb.append(" ");
- }
- sb.append(quotient)
- .append(" ")
- .append(resources.getQuantityString(UNITS[i], (int) quotient));
- start = true;
- }
- leftover = remainder;
- }
-
- return sb.toString();
- }
-
public static String getShortTimeInterval(long time) {
StringBuilder sb = new StringBuilder();
Resources resources = sResources;
@@ -173,8 +127,8 @@ public final class ReadableTime {
}
public static String getFilenamableTime(long time) {
- synchronized (sDateFormatLock2) {
- return FILENAMABLE_DATE_FORMAT.format(new Date(time));
+ synchronized (sDateFormatLock) {
+ return FILENAMABLE_DATE_FORMAT.format(Instant.ofEpochMilli(time));
}
}
}