使用 Instant 替代 Date (#2713)

* update

* update

* update

* update

* update

* Update

* update

* update

* Add more tests

* fix checkstyle
This commit is contained in:
Glavo
2024-02-13 15:29:54 +08:00
committed by GitHub
parent 95707560ef
commit 5d26a106e9
25 changed files with 177 additions and 231 deletions

View File

@@ -22,7 +22,7 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.ToStringBuilder;
import org.jackhuang.hmcl.util.versioning.VersionNumber;
import java.util.Date;
import java.time.Instant;
import java.util.List;
import java.util.Objects;
@@ -36,7 +36,7 @@ public class RemoteVersion implements Comparable<RemoteVersion> {
private final String libraryId;
private final String gameVersion;
private final String selfVersion;
private final Date releaseDate;
private final Instant releaseDate;
private final List<String> urls;
private final Type type;
@@ -47,7 +47,7 @@ public class RemoteVersion implements Comparable<RemoteVersion> {
* @param selfVersion the version string of the remote version.
* @param urls the installer or universal jar original URL.
*/
public RemoteVersion(String libraryId, String gameVersion, String selfVersion, Date releaseDate, List<String> urls) {
public RemoteVersion(String libraryId, String gameVersion, String selfVersion, Instant releaseDate, List<String> urls) {
this(libraryId, gameVersion, selfVersion, releaseDate, Type.UNCATEGORIZED, urls);
}
@@ -58,7 +58,7 @@ public class RemoteVersion implements Comparable<RemoteVersion> {
* @param selfVersion the version string of the remote version.
* @param urls the installer or universal jar URL.
*/
public RemoteVersion(String libraryId, String gameVersion, String selfVersion, Date releaseDate, Type type, List<String> urls) {
public RemoteVersion(String libraryId, String gameVersion, String selfVersion, Instant releaseDate, Type type, List<String> urls) {
this.libraryId = Objects.requireNonNull(libraryId);
this.gameVersion = Objects.requireNonNull(gameVersion);
this.selfVersion = Objects.requireNonNull(selfVersion);
@@ -83,7 +83,7 @@ public class RemoteVersion implements Comparable<RemoteVersion> {
return getSelfVersion();
}
public Date getReleaseDate() {
public Instant getReleaseDate() {
return releaseDate;
}

View File

@@ -24,7 +24,7 @@ import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.mod.RemoteMod;
import org.jackhuang.hmcl.task.Task;
import java.util.Date;
import java.time.Instant;
import java.util.List;
public class FabricAPIRemoteVersion extends RemoteVersion {
@@ -38,7 +38,7 @@ public class FabricAPIRemoteVersion extends RemoteVersion {
* @param selfVersion the version string of the remote version.
* @param urls the installer or universal jar original URL.
*/
FabricAPIRemoteVersion(String gameVersion, String selfVersion, String fullVersion, Date datePublished, RemoteMod.Version version, List<String> urls) {
FabricAPIRemoteVersion(String gameVersion, String selfVersion, String fullVersion, Instant datePublished, RemoteMod.Version version, List<String> urls) {
super(LibraryAnalyzer.LibraryType.FABRIC_API.getPatchId(), gameVersion, selfVersion, datePublished, urls);
this.fullVersion = fullVersion;

View File

@@ -109,7 +109,7 @@ public final class ForgeBMCLVersionList extends VersionList<ForgeRemoteVersion>
}
versions.put(gameVersion, new ForgeRemoteVersion(
version.getGameVersion(), version.getVersion(), releaseDate == null ? null : Date.from(releaseDate), urls));
version.getGameVersion(), version.getVersion(), releaseDate, urls));
}
} finally {
lock.writeLock().unlock();

View File

@@ -23,7 +23,7 @@ import org.jackhuang.hmcl.download.RemoteVersion;
import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.task.Task;
import java.util.Date;
import java.time.Instant;
import java.util.List;
public class ForgeRemoteVersion extends RemoteVersion {
@@ -34,7 +34,7 @@ public class ForgeRemoteVersion extends RemoteVersion {
* @param selfVersion the version string of the remote version.
* @param url the installer or universal jar original URL.
*/
public ForgeRemoteVersion(String gameVersion, String selfVersion, Date releaseDate, List<String> url) {
public ForgeRemoteVersion(String gameVersion, String selfVersion, Instant releaseDate, List<String> url) {
super(LibraryAnalyzer.LibraryType.FORGE.getPatchId(), gameVersion, selfVersion, releaseDate, url);
}

View File

@@ -25,7 +25,7 @@ import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.Immutable;
import java.util.Date;
import java.time.Instant;
import java.util.List;
/**
@@ -37,7 +37,7 @@ public final class GameRemoteVersion extends RemoteVersion {
private final ReleaseType type;
public GameRemoteVersion(String gameVersion, String selfVersion, List<String> url, ReleaseType type, Date releaseDate) {
public GameRemoteVersion(String gameVersion, String selfVersion, List<String> url, ReleaseType type, Instant releaseDate) {
super(LibraryAnalyzer.LibraryType.MINECRAFT.getPatchId(), gameVersion, selfVersion, releaseDate, getReleaseType(type), url);
this.type = type;
}

View File

@@ -24,7 +24,7 @@ import org.jackhuang.hmcl.util.Constants;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.gson.Validation;
import java.util.Date;
import java.time.Instant;
/**
*
@@ -36,10 +36,10 @@ public final class GameRemoteVersionInfo implements Validation {
private final String gameVersion;
@SerializedName("time")
private final Date time;
private final Instant time;
@SerializedName("releaseTime")
private final Date releaseTime;
private final Instant releaseTime;
@SerializedName("type")
private final ReleaseType type;
@@ -48,14 +48,14 @@ public final class GameRemoteVersionInfo implements Validation {
private final String url;
public GameRemoteVersionInfo() {
this("", new Date(), new Date(), ReleaseType.UNKNOWN);
this("", Instant.now(), Instant.now(), ReleaseType.UNKNOWN);
}
public GameRemoteVersionInfo(String gameVersion, Date time, Date releaseTime, ReleaseType type) {
public GameRemoteVersionInfo(String gameVersion, Instant time, Instant releaseTime, ReleaseType type) {
this(gameVersion, time, releaseTime, type, Constants.DEFAULT_LIBRARY_URL + gameVersion + "/" + gameVersion + ".json");
}
public GameRemoteVersionInfo(String gameVersion, Date time, Date releaseTime, ReleaseType type, String url) {
public GameRemoteVersionInfo(String gameVersion, Instant time, Instant releaseTime, ReleaseType type, String url) {
this.gameVersion = gameVersion;
this.time = time;
this.releaseTime = releaseTime;
@@ -67,11 +67,11 @@ public final class GameRemoteVersionInfo implements Validation {
return gameVersion;
}
public Date getTime() {
public Instant getTime() {
return time;
}
public Date getReleaseTime() {
public Instant getReleaseTime() {
return releaseTime;
}

View File

@@ -24,7 +24,7 @@ import org.jackhuang.hmcl.game.Version;
import org.jackhuang.hmcl.mod.RemoteMod;
import org.jackhuang.hmcl.task.Task;
import java.util.Date;
import java.time.Instant;
import java.util.List;
public class QuiltAPIRemoteVersion extends RemoteVersion {
@@ -38,7 +38,7 @@ public class QuiltAPIRemoteVersion extends RemoteVersion {
* @param selfVersion the version string of the remote version.
* @param urls the installer or universal jar original URL.
*/
QuiltAPIRemoteVersion(String gameVersion, String selfVersion, String fullVersion, Date datePublished, RemoteMod.Version version, List<String> urls) {
QuiltAPIRemoteVersion(String gameVersion, String selfVersion, String fullVersion, Instant datePublished, RemoteMod.Version version, List<String> urls) {
super(LibraryAnalyzer.LibraryType.QUILT_API.getPatchId(), gameVersion, selfVersion, datePublished, urls);
this.fullVersion = fullVersion;

View File

@@ -18,8 +18,8 @@
package org.jackhuang.hmcl.game;
import java.io.File;
import java.time.Instant;
import java.util.Arrays;
import java.util.Date;
/**
* The Minecraft version for 1.5.x and earlier.
@@ -32,7 +32,7 @@ public class ClassicVersion extends Version {
super(true, "Classic", null, null, "${auth_player_name} ${auth_session} --workDir ${game_directory}",
null, "net.minecraft.client.Minecraft", null, null, null, null, null, null,
Arrays.asList(new ClassicLibrary("lwjgl"), new ClassicLibrary("jinput"), new ClassicLibrary("lwjgl_util")),
null, null, null, ReleaseType.UNKNOWN, new Date(), new Date(), 0, false, false, null);
null, null, null, ReleaseType.UNKNOWN, Instant.now(), Instant.now(), 0, false, false, null);
}
private static class ClassicLibrary extends Library {

View File

@@ -28,10 +28,10 @@ import org.jackhuang.hmcl.util.gson.JsonMap;
import org.jackhuang.hmcl.util.gson.Validation;
import org.jetbrains.annotations.Nullable;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -66,8 +66,8 @@ public class Version implements Comparable<Version>, Validation {
private final JsonMap<DownloadType, DownloadInfo> downloads;
private final JsonMap<DownloadType, LoggingInfo> logging;
private final ReleaseType type;
private final Date time;
private final Date releaseTime;
private final Instant time;
private final Instant releaseTime;
private final Integer minimumLauncherVersion;
private final Boolean root;
private final Boolean hidden;
@@ -93,7 +93,7 @@ public class Version implements Comparable<Version>, Validation {
this(false, id, version, priority, null, arguments, mainClass, null, null, null, null, null, null, libraries, null, null, null, null, null, null, null, null, null, null);
}
public Version(boolean resolved, String id, String version, Integer priority, String minecraftArguments, Arguments arguments, String mainClass, String inheritsFrom, String jar, AssetIndexInfo assetIndex, String assets, Integer complianceLevel, GameJavaVersion javaVersion, List<Library> libraries, List<CompatibilityRule> compatibilityRules, Map<DownloadType, DownloadInfo> downloads, Map<DownloadType, LoggingInfo> logging, ReleaseType type, Date time, Date releaseTime, Integer minimumLauncherVersion, Boolean hidden, Boolean root, List<Version> patches) {
public Version(boolean resolved, String id, String version, Integer priority, String minecraftArguments, Arguments arguments, String mainClass, String inheritsFrom, String jar, AssetIndexInfo assetIndex, String assets, Integer complianceLevel, GameJavaVersion javaVersion, List<Library> libraries, List<CompatibilityRule> compatibilityRules, Map<DownloadType, DownloadInfo> downloads, Map<DownloadType, LoggingInfo> logging, ReleaseType type, Instant time, Instant releaseTime, Integer minimumLauncherVersion, Boolean hidden, Boolean root, List<Version> patches) {
this.resolved = resolved;
this.id = id;
this.version = version;
@@ -112,8 +112,8 @@ public class Version implements Comparable<Version>, Validation {
this.downloads = downloads == null ? null : new JsonMap<>(downloads);
this.logging = logging == null ? null : new JsonMap<>(logging);
this.type = type;
this.time = time == null ? null : (Date) time.clone();
this.releaseTime = releaseTime == null ? null : (Date) releaseTime.clone();
this.time = time;
this.releaseTime = releaseTime;
this.minimumLauncherVersion = minimumLauncherVersion;
this.hidden = hidden;
this.root = root;
@@ -132,7 +132,7 @@ public class Version implements Comparable<Version>, Validation {
return mainClass;
}
public Date getTime() {
public Instant getTime() {
return time;
}
@@ -158,7 +158,7 @@ public class Version implements Comparable<Version>, Validation {
return type == null ? ReleaseType.UNKNOWN : type;
}
public Date getReleaseTime() {
public Instant getReleaseTime() {
return releaseTime;
}

View File

@@ -24,7 +24,7 @@ import org.jackhuang.hmcl.util.gson.TolerableValidationException;
import org.jackhuang.hmcl.util.gson.Validation;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;
@@ -46,12 +46,12 @@ public class TLauncherVersion implements Validation {
private final JsonMap<DownloadType, DownloadInfo> downloads;
private final JsonMap<DownloadType, LoggingInfo> logging;
private final ReleaseType type;
private final Date time;
private final Date releaseTime;
private final Instant time;
private final Instant releaseTime;
private final Integer minimumLauncherVersion;
private final Integer tlauncherVersion;
public TLauncherVersion(String id, String minecraftArguments, Arguments arguments, String mainClass, String inheritsFrom, String jar, AssetIndexInfo assetIndex, String assets, Integer complianceLevel, @Nullable GameJavaVersion javaVersion, List<TLauncherLibrary> libraries, List<CompatibilityRule> compatibilityRules, JsonMap<DownloadType, DownloadInfo> downloads, JsonMap<DownloadType, LoggingInfo> logging, ReleaseType type, Date time, Date releaseTime, Integer minimumLauncherVersion, Integer tlauncherVersion) {
public TLauncherVersion(String id, String minecraftArguments, Arguments arguments, String mainClass, String inheritsFrom, String jar, AssetIndexInfo assetIndex, String assets, Integer complianceLevel, @Nullable GameJavaVersion javaVersion, List<TLauncherLibrary> libraries, List<CompatibilityRule> compatibilityRules, JsonMap<DownloadType, DownloadInfo> downloads, JsonMap<DownloadType, LoggingInfo> logging, ReleaseType type, Instant time, Instant releaseTime, Integer minimumLauncherVersion, Integer tlauncherVersion) {
this.id = id;
this.minecraftArguments = minecraftArguments;
this.arguments = arguments;

View File

@@ -22,7 +22,7 @@ import org.jackhuang.hmcl.mod.modrinth.ModrinthRemoteModRepository;
import org.jackhuang.hmcl.task.FileDownloadTask;
import java.io.IOException;
import java.util.Date;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
@@ -218,14 +218,14 @@ public class RemoteMod {
private final String name;
private final String version;
private final String changelog;
private final Date datePublished;
private final Instant datePublished;
private final VersionType versionType;
private final File file;
private final List<Dependency> dependencies;
private final List<String> gameVersions;
private final List<ModLoaderType> loaders;
public Version(IVersion self, String modid, String name, String version, String changelog, Date datePublished, VersionType versionType, File file, List<Dependency> dependencies, List<String> gameVersions, List<ModLoaderType> loaders) {
public Version(IVersion self, String modid, String name, String version, String changelog, Instant datePublished, VersionType versionType, File file, List<Dependency> dependencies, List<String> gameVersions, List<ModLoaderType> loaders) {
this.self = self;
this.modid = modid;
this.name = name;
@@ -259,7 +259,7 @@ public class RemoteMod {
return changelog;
}
public Date getDatePublished() {
public Instant getDatePublished() {
return datePublished;
}

View File

@@ -26,6 +26,7 @@ import org.jackhuang.hmcl.util.Pair;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -58,15 +59,15 @@ public class CurseAddon implements RemoteMod.IMod {
private final int mainFileId;
private final List<LatestFile> latestFiles;
private final List<LatestFileIndex> latestFileIndices;
private final Date dateCreated;
private final Date dateModified;
private final Date dateReleased;
private final Instant dateCreated;
private final Instant dateModified;
private final Instant dateReleased;
private final boolean allowModDistribution;
private final int gamePopularityRank;
private final boolean isAvailable;
private final int thumbsUpCount;
public CurseAddon(int id, int gameId, String name, String slug, Links links, String summary, int status, int downloadCount, boolean isFeatured, int primaryCategoryId, List<Category> categories, int classId, List<Author> authors, Logo logo, int mainFileId, List<LatestFile> latestFiles, List<LatestFileIndex> latestFileIndices, Date dateCreated, Date dateModified, Date dateReleased, boolean allowModDistribution, int gamePopularityRank, boolean isAvailable, int thumbsUpCount) {
public CurseAddon(int id, int gameId, String name, String slug, Links links, String summary, int status, int downloadCount, boolean isFeatured, int primaryCategoryId, List<Category> categories, int classId, List<Author> authors, Logo logo, int mainFileId, List<LatestFile> latestFiles, List<LatestFileIndex> latestFileIndices, Instant dateCreated, Instant dateModified, Instant dateReleased, boolean allowModDistribution, int gamePopularityRank, boolean isAvailable, int thumbsUpCount) {
this.id = id;
this.gameId = gameId;
this.name = name;
@@ -161,15 +162,15 @@ public class CurseAddon implements RemoteMod.IMod {
return latestFileIndices;
}
public Date getDateCreated() {
public Instant getDateCreated() {
return dateCreated;
}
public Date getDateModified() {
public Instant getDateModified() {
return dateModified;
}
public Date getDateReleased() {
public Instant getDateReleased() {
return dateReleased;
}
@@ -438,7 +439,7 @@ public class CurseAddon implements RemoteMod.IMod {
private final int releaseType;
private final int fileStatus;
private final List<LatestFileHash> hashes;
private final Date fileDate;
private final Instant fileDate;
private final int fileLength;
private final int downloadCount;
private final String downloadUrl;
@@ -448,7 +449,7 @@ public class CurseAddon implements RemoteMod.IMod {
private final boolean isServerPack;
private final long fileFingerprint;
public LatestFile(int id, int gameId, int modId, boolean isAvailable, String displayName, String fileName, int releaseType, int fileStatus, List<LatestFileHash> hashes, Date fileDate, int fileLength, int downloadCount, String downloadUrl, List<String> gameVersions, List<Dependency> dependencies, int alternateFileId, boolean isServerPack, long fileFingerprint) {
public LatestFile(int id, int gameId, int modId, boolean isAvailable, String displayName, String fileName, int releaseType, int fileStatus, List<LatestFileHash> hashes, Instant fileDate, int fileLength, int downloadCount, String downloadUrl, List<String> gameVersions, List<Dependency> dependencies, int alternateFileId, boolean isServerPack, long fileFingerprint) {
this.id = id;
this.gameId = gameId;
this.modId = modId;
@@ -505,7 +506,7 @@ public class CurseAddon implements RemoteMod.IMod {
return hashes;
}
public Date getFileDate() {
public Instant getFileDate() {
return fileDate;
}
@@ -650,7 +651,7 @@ public class CurseAddon implements RemoteMod.IMod {
private final String slug;
private final String url;
private final String iconUrl;
private final Date dateModified;
private final Instant dateModified;
private final boolean isClass;
private final int classId;
private final int parentCategoryId;
@@ -658,10 +659,10 @@ public class CurseAddon implements RemoteMod.IMod {
private transient final List<Category> subcategories;
public Category() {
this(0, 0, "", "", "", "", new Date(), false, 0, 0);
this(0, 0, "", "", "", "", Instant.now(), false, 0, 0);
}
public Category(int id, int gameId, String name, String slug, String url, String iconUrl, Date dateModified, boolean isClass, int classId, int parentCategoryId) {
public Category(int id, int gameId, String name, String slug, String url, String iconUrl, Instant dateModified, boolean isClass, int classId, int parentCategoryId) {
this.id = id;
this.gameId = gameId;
this.name = name;
@@ -700,7 +701,7 @@ public class CurseAddon implements RemoteMod.IMod {
return iconUrl;
}
public Date getDateModified() {
public Instant getDateModified() {
return dateModified;
}

View File

@@ -32,6 +32,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.nio.file.Path;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -210,13 +211,13 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
private final String team;
private final Date published;
private final Instant published;
private final Date updated;
private final Instant updated;
private final List<String> versions;
public Project(String slug, String title, String description, List<String> categories, String body, String projectType, int downloads, String iconUrl, String id, String team, Date published, Date updated, List<String> versions) {
public Project(String slug, String title, String description, List<String> categories, String body, String projectType, int downloads, String iconUrl, String id, String team, Instant published, Instant updated, List<String> versions) {
this.slug = slug;
this.title = title;
this.description = description;
@@ -272,11 +273,11 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
return team;
}
public Date getPublished() {
public Instant getPublished() {
return published;
}
public Date getUpdated() {
public Instant getUpdated() {
return updated;
}
@@ -381,7 +382,7 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
private final String authorId;
@SerializedName("date_published")
private final Date datePublished;
private final Instant datePublished;
private final int downloads;
@@ -390,7 +391,7 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
private final List<ProjectVersionFile> files;
public ProjectVersion(String name, String versionNumber, String changelog, List<Dependency> dependencies, List<String> gameVersions, String versionType, List<String> loaders, boolean featured, String id, String projectId, String authorId, Date datePublished, int downloads, String changelogUrl, List<ProjectVersionFile> files) {
public ProjectVersion(String name, String versionNumber, String changelog, List<Dependency> dependencies, List<String> gameVersions, String versionType, List<String> loaders, boolean featured, String id, String projectId, String authorId, Instant datePublished, int downloads, String changelogUrl, List<ProjectVersionFile> files) {
this.name = name;
this.versionNumber = versionNumber;
this.changelog = changelog;
@@ -452,7 +453,7 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
return authorId;
}
public Date getDatePublished() {
public Instant getDatePublished() {
return datePublished;
}
@@ -587,15 +588,15 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
private final List<String> versions;
@SerializedName("date_created")
private final Date dateCreated;
private final Instant dateCreated;
@SerializedName("date_modified")
private final Date dateModified;
private final Instant dateModified;
@SerializedName("latest_version")
private final String latestVersion;
public ProjectSearchResult(String slug, String title, String description, List<String> categories, String projectType, int downloads, String iconUrl, String projectId, String author, List<String> versions, Date dateCreated, Date dateModified, String latestVersion) {
public ProjectSearchResult(String slug, String title, String description, List<String> categories, String projectType, int downloads, String iconUrl, String projectId, String author, List<String> versions, Instant dateCreated, Instant dateModified, String latestVersion) {
this.slug = slug;
this.title = title;
this.description = description;
@@ -651,11 +652,11 @@ public final class ModrinthRemoteModRepository implements RemoteModRepository {
return versions;
}
public Date getDateCreated() {
public Instant getDateCreated() {
return dateCreated;
}
public Date getDateModified() {
public Instant getDateModified() {
return dateModified;
}

View File

@@ -22,9 +22,10 @@ import org.jackhuang.hmcl.util.io.IOUtils;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.logging.*;
/**
@@ -120,35 +121,39 @@ public final class Logging {
}
}
private static final MessageFormat FORMAT = new MessageFormat("[{0,date,HH:mm:ss}] [{1}.{2}/{3}] {4}\n");
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneId.systemDefault());
private static String format(LogRecord record) {
String message = filterForbiddenToken(record.getMessage());
StringBuilder builder = new StringBuilder(128 + message.length());
builder.append('[');
TIME_FORMATTER.formatTo(Instant.ofEpochMilli(record.getMillis()), builder);
builder.append(']');
builder.append(" [")
.append(record.getSourceClassName())
.append('.')
.append(record.getSourceMethodName())
.append('/')
.append(record.getLevel().getName())
.append("] ")
.append(message)
.append('\n');
Throwable thrown = record.getThrown();
StringWriter writer;
StringBuffer buffer;
if (thrown == null) {
writer = null;
buffer = new StringBuffer(256);
return builder.toString();
} else {
writer = new StringWriter(1024);
buffer = writer.getBuffer();
}
FORMAT.format(new Object[]{
new Date(record.getMillis()),
record.getSourceClassName(), record.getSourceMethodName(), record.getLevel().getName(),
message
}, buffer, null);
if (thrown != null) {
StringWriter writer = new StringWriter(builder.length() + 2048);
writer.getBuffer().append(builder);
try (PrintWriter printWriter = new PrintWriter(writer)) {
thrown.printStackTrace(printWriter);
}
return writer.toString();
}
return buffer.toString();
}
private static final class DefaultFormatter extends Formatter {

View File

@@ -1,106 +0,0 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2020 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.gson;
import com.google.gson.*;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.Locale;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME;
/**
*
* @author huangyuhui
*/
public final class DateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
public static final DateTypeAdapter INSTANCE = new DateTypeAdapter();
private DateTypeAdapter() {
}
@Override
public JsonElement serialize(Date t, Type type, JsonSerializationContext jsc) {
synchronized (EN_US_FORMAT) {
return new JsonPrimitive(serializeToString(t));
}
}
@Override
public Date deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
if (!(json instanceof JsonPrimitive))
throw new JsonParseException("The date should be a string value");
else {
Date date = deserializeToDate(json.getAsString());
if (type == Date.class)
return date;
else
throw new IllegalArgumentException(this.getClass().toString() + " cannot be deserialized to " + type);
}
}
public static final DateFormat EN_US_FORMAT = DateFormat.getDateTimeInstance(2, 2, Locale.US);
public static final DateFormat ISO_8601_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
public static final DateTimeFormatter ISO_DATE_TIME = new DateTimeFormatterBuilder()
.append(ISO_LOCAL_DATE_TIME)
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHMM", "+0000").optionalEnd()
.optionalStart().appendOffset("+HH", "Z").optionalEnd()
.optionalStart().appendOffsetId().optionalEnd()
.toFormatter();
public static Date deserializeToDate(String string) {
synchronized (EN_US_FORMAT) {
try {
return EN_US_FORMAT.parse(string);
} catch (ParseException ex1) {
try {
ZonedDateTime zonedDateTime = ZonedDateTime.parse(string, ISO_DATE_TIME);
return Date.from(zonedDateTime.toInstant());
} catch (DateTimeParseException e) {
try {
LocalDateTime localDateTime = LocalDateTime.parse(string, ISO_LOCAL_DATE_TIME);
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
} catch (DateTimeParseException e2) {
throw new JsonParseException("Invalid date: " + string, e);
}
}
}
}
}
public static String serializeToString(Date date) {
synchronized (EN_US_FORMAT) {
String result = ISO_8601_FORMAT.format(date);
return result.substring(0, 22) + ":" + result.substring(22);
}
}
}

View File

@@ -20,9 +20,15 @@ package org.jackhuang.hmcl.util.gson;
import com.google.gson.*;
import java.lang.reflect.Type;
import java.time.Instant;
import java.time.ZoneId;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoUnit;
import java.util.Locale;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME;
public final class InstantTypeAdapter implements JsonSerializer<Instant>, JsonDeserializer<Instant> {
public static final InstantTypeAdapter INSTANCE = new InstantTypeAdapter();
@@ -31,21 +37,53 @@ public final class InstantTypeAdapter implements JsonSerializer<Instant>, JsonDe
}
@Override
public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!(json instanceof JsonPrimitive)) {
public JsonElement serialize(Instant t, Type type, JsonSerializationContext jsc) {
return new JsonPrimitive(serializeToString(t, ZoneId.systemDefault()));
}
@Override
public Instant deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
if (!(json instanceof JsonPrimitive))
throw new JsonParseException("The instant should be a string value");
} else {
Instant instant = Instant.parse(json.getAsString());
if (typeOfT == Instant.class) {
return instant;
} else {
throw new IllegalArgumentException(this.getClass() + " cannot be deserialized to " + typeOfT);
else {
Instant time = deserializeToInstant(json.getAsString());
if (type == Instant.class)
return time;
else
throw new IllegalArgumentException(this.getClass() + " cannot be deserialized to " + type);
}
}
private static final DateTimeFormatter EN_US_FORMAT = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.MEDIUM)
.withLocale(Locale.US)
.withZone(ZoneId.systemDefault());
private static final DateTimeFormatter ISO_DATE_TIME = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.optionalStart().appendOffset("+HH:MM", "+00:00").optionalEnd()
.optionalStart().appendOffset("+HHMM", "+0000").optionalEnd()
.optionalStart().appendOffset("+HH", "Z").optionalEnd()
.optionalStart().appendOffsetId().optionalEnd()
.toFormatter();
public static Instant deserializeToInstant(String string) {
try {
return ZonedDateTime.parse(string, EN_US_FORMAT).toInstant();
} catch (DateTimeParseException ex1) {
try {
ZonedDateTime zonedDateTime = ZonedDateTime.parse(string, ISO_DATE_TIME);
return zonedDateTime.toInstant();
} catch (DateTimeParseException e) {
try {
LocalDateTime localDateTime = LocalDateTime.parse(string, ISO_LOCAL_DATE_TIME);
return localDateTime.atZone(ZoneId.systemDefault()).toInstant();
} catch (DateTimeParseException e2) {
throw new JsonParseException("Invalid instant: " + string, e);
}
}
}
}
@Override
public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.systemDefault()).format(src));
public static String serializeToString(Instant instant, ZoneId zone) {
return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.ofInstant(instant, zone).truncatedTo(ChronoUnit.SECONDS));
}
}

View File

@@ -29,7 +29,6 @@ import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;
/**
@@ -113,7 +112,6 @@ public final class JsonUtils {
.enableComplexMapKeySerialization()
.setPrettyPrinting()
.registerTypeAdapter(Instant.class, InstantTypeAdapter.INSTANCE)
.registerTypeAdapter(Date.class, DateTypeAdapter.INSTANCE)
.registerTypeAdapter(UUID.class, UUIDTypeAdapter.INSTANCE)
.registerTypeAdapter(File.class, FileTypeAdapter.INSTANCE)
.registerTypeAdapterFactory(ValidationTypeAdapterFactory.INSTANCE)

View File

@@ -2,29 +2,38 @@ package org.jackhuang.hmcl.util.gson;
import org.junit.jupiter.api.Test;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import static org.junit.jupiter.api.Assertions.*;
public class DateTypeAdapterTest {
public class InstantTypeAdapterTest {
@Test
public void parse() {
public void testDeserialize() {
assertEquals(
LocalDateTime.of(2017, 6, 8, 4, 26, 33)
.atOffset(ZoneOffset.UTC).toInstant(),
DateTypeAdapter.deserializeToDate("2017-06-08T04:26:33+0000").toInstant());
InstantTypeAdapter.deserializeToInstant("2017-06-08T04:26:33+0000"));
assertEquals(
LocalDateTime.of(2021, 1, 3, 0, 53, 34)
.atOffset(ZoneOffset.UTC).toInstant(),
DateTypeAdapter.deserializeToDate("2021-01-03T00:53:34+00:00").toInstant());
InstantTypeAdapter.deserializeToInstant("2021-01-03T00:53:34+00:00"));
assertEquals(
LocalDateTime.of(2021, 1, 3, 0, 53, 34)
.atZone(ZoneId.systemDefault()).toInstant(),
DateTypeAdapter.deserializeToDate("2021-01-03T00:53:34").toInstant());
InstantTypeAdapter.deserializeToInstant("2021-01-03T00:53:34"));
}
@Test
public void testSerialize() {
assertEquals(
"2024-02-13T15:11:06+08:00",
InstantTypeAdapter.serializeToString(Instant.ofEpochMilli(1707808266154L), ZoneOffset.ofHours(8))
);
}
}