diff --git a/src/main/java/org/traccar/database/MediaManager.java b/src/main/java/org/traccar/database/MediaManager.java index 697699a39..eb602f1ac 100644 --- a/src/main/java/org/traccar/database/MediaManager.java +++ b/src/main/java/org/traccar/database/MediaManager.java @@ -32,14 +32,18 @@ import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; @Singleton public class MediaManager { private static final Logger LOGGER = LoggerFactory.getLogger(MediaManager.class); + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyyMMddHHmmss").withZone(ZoneId.systemDefault()); + private final Path path; @Inject @@ -67,7 +71,7 @@ public class MediaManager { public String writeFile(String uniqueId, ByteBuf buf, String extension) { if (path != null) { int size = buf.readableBytes(); - String name = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "." + extension; + String name = DATE_FORMAT.format(Instant.now()) + "." + extension; try (FileOutputStream output = new FileOutputStream(createFile(uniqueId, name)); FileChannel fileChannel = output.getChannel()) { ByteBuffer byteBuffer = buf.nioBuffer(); diff --git a/src/main/java/org/traccar/helper/DateUtil.java b/src/main/java/org/traccar/helper/DateUtil.java index 20a483e3c..49d16c687 100644 --- a/src/main/java/org/traccar/helper/DateUtil.java +++ b/src/main/java/org/traccar/helper/DateUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 Anton Tananaev (anton@traccar.org) + * Copyright 2016 - 2026 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,6 +63,10 @@ public final class DateUtil { return Date.from(Instant.from(DateTimeFormatter.ISO_ZONED_DATE_TIME.parse(value))); } + public static Date parse(DateTimeFormatter formatter, String value) { + return Date.from(Instant.from(formatter.parse(value))); + } + public static String formatDate(Date date) { return formatDate(date, true); } diff --git a/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java index b4bf8379a..10472fbec 100644 --- a/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/AtrackProtocolDecoder.java @@ -27,6 +27,7 @@ import org.traccar.config.Keys; import org.traccar.helper.BitUtil; import org.traccar.helper.DataConverter; import org.traccar.helper.DateBuilder; +import org.traccar.helper.DateUtil; import org.traccar.helper.Parser; import org.traccar.helper.PatternBuilder; import org.traccar.helper.UnitsConverter; @@ -36,20 +37,21 @@ import org.traccar.model.Position; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; public class AtrackProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyyMMddHHmmss").withZone(ZoneOffset.UTC); + private static final int MIN_DATA_LENGTH = 40; private boolean longDate; @@ -547,13 +549,7 @@ public class AtrackProtocolDecoder extends BaseProtocolDecoder { String time = parser.next(); if (time.length() >= 14) { - try { - DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - position.setTime(dateFormat.parse(time)); - } catch (ParseException e) { - throw new RuntimeException(e); - } + position.setTime(DateUtil.parse(DATE_FORMAT, time)); } else { position.setTime(new Date(Long.parseLong(time) * 1000)); } diff --git a/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java b/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java index 672848174..734557e2d 100644 --- a/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/DmtHttpProtocolDecoder.java @@ -22,6 +22,7 @@ import org.traccar.BaseHttpProtocolDecoder; import org.traccar.session.DeviceSession; import org.traccar.Protocol; import org.traccar.helper.BitUtil; +import org.traccar.helper.DateUtil; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; @@ -31,18 +32,19 @@ import jakarta.json.JsonObject; import java.io.StringReader; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.Collection; import java.util.Date; import java.util.LinkedList; import java.util.List; -import java.util.TimeZone; public class DmtHttpProtocolDecoder extends BaseHttpProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC); + public DmtHttpProtocolDecoder(Protocol protocol) { super(protocol); } @@ -67,10 +69,7 @@ public class DmtHttpProtocolDecoder extends BaseHttpProtocolDecoder { } private Collection decodeTraditional( - Channel channel, SocketAddress remoteAddress, JsonObject root) throws ParseException { - - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + Channel channel, SocketAddress remoteAddress, JsonObject root) { DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, root.getString("IMEI")); if (deviceSession == null) { @@ -90,7 +89,7 @@ public class DmtHttpProtocolDecoder extends BaseHttpProtocolDecoder { position.set(Position.KEY_INDEX, record.getInt("SeqNo")); position.set(Position.KEY_EVENT, record.getInt("Reason")); - position.setDeviceTime(dateFormat.parse(record.getString("DateUTC"))); + position.setDeviceTime(DateUtil.parse(DATE_FORMAT, record.getString("DateUTC"))); JsonArray fields = record.getJsonArray("Fields"); @@ -98,7 +97,7 @@ public class DmtHttpProtocolDecoder extends BaseHttpProtocolDecoder { JsonObject field = fields.getJsonObject(j); switch (field.getInt("FType")) { case 0: - position.setFixTime(dateFormat.parse(field.getString("GpsUTC"))); + position.setFixTime(DateUtil.parse(DATE_FORMAT, field.getString("GpsUTC"))); position.setLatitude(field.getJsonNumber("Lat").doubleValue()); position.setLongitude(field.getJsonNumber("Long").doubleValue()); position.setAltitude(field.getInt("Alt")); diff --git a/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java index a92eb40d7..aab7d3c33 100644 --- a/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/FifotrackProtocolDecoder.java @@ -34,14 +34,16 @@ import org.traccar.model.WifiAccessPoint; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.regex.Pattern; public class FifotrackProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyMMddHHmmss").withZone(ZoneOffset.UTC); + private ByteBuf photo; public FifotrackProtocolDecoder(Protocol protocol) { @@ -240,9 +242,7 @@ public class FifotrackProtocolDecoder extends BaseProtocolDecoder { position.setNetwork(network); - DateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - String response = index + ",A03," + dateFormat.format(new Date()); + String response = index + ",A03," + DATE_FORMAT.format(Instant.now()); sendResponse(channel, remoteAddress, imei, response); return position; diff --git a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java index 053fd5c26..934785603 100644 --- a/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/GlobalstarProtocolDecoder.java @@ -58,13 +58,19 @@ import javax.xml.xpath.XPathFactory; import java.io.StringReader; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.LinkedList; import java.util.List; +import java.util.Locale; public class GlobalstarProtocolDecoder extends BaseHttpProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("dd/MM/yyyy hh:mm:ss z", Locale.ENGLISH).withZone(ZoneId.systemDefault()); + private final DocumentBuilder documentBuilder; private final XPath xPath; private final XPathExpression messageExpression; @@ -94,7 +100,7 @@ public class GlobalstarProtocolDecoder extends BaseHttpProtocolDecoder { rootElement.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); rootElement.setAttribute( "xsi:noNamespaceSchemaLocation", "http://cody.glpconnect.com/XSD/StuResponse_Rev1_0.xsd"); - rootElement.setAttribute("deliveryTimeStamp", new SimpleDateFormat("dd/MM/yyyy hh:mm:ss z").format(new Date())); + rootElement.setAttribute("deliveryTimeStamp", DATE_FORMAT.format(Instant.now())); rootElement.setAttribute("messageID", "00000000000000000000000000000000"); rootElement.setAttribute("correlationID", messageId); document.appendChild(rootElement); diff --git a/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java b/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java index 30b412f92..b042e5fc7 100644 --- a/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/ItsProtocolDecoder.java @@ -28,14 +28,16 @@ import org.traccar.model.Network; import org.traccar.model.Position; import java.net.SocketAddress; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.regex.Pattern; public class ItsProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("ddMMyyyyHHmmss").withZone(ZoneOffset.UTC); + public ItsProtocolDecoder(Protocol protocol) { super(protocol); } @@ -140,9 +142,7 @@ public class ItsProtocolDecoder extends BaseProtocolDecoder { if (sentence.startsWith("$,01,")) { channel.writeAndFlush(new NetworkMessage("$,1,*", remoteAddress)); } else if (sentence.startsWith("$,LGN,")) { - DateFormat dateFormat = new SimpleDateFormat("ddMMyyyyHHmmss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - String time = dateFormat.format(new Date()); + String time = DATE_FORMAT.format(Instant.now()); channel.writeAndFlush(new NetworkMessage("$LGN" + time + "*", remoteAddress)); } else if (sentence.startsWith("$,HBT,")) { channel.writeAndFlush(new NetworkMessage("$HBT*", remoteAddress)); diff --git a/src/main/java/org/traccar/protocol/Jt808ProtocolEncoder.java b/src/main/java/org/traccar/protocol/Jt808ProtocolEncoder.java index 877fca3b7..744f7367e 100644 --- a/src/main/java/org/traccar/protocol/Jt808ProtocolEncoder.java +++ b/src/main/java/org/traccar/protocol/Jt808ProtocolEncoder.java @@ -30,12 +30,16 @@ import org.traccar.model.Command; import java.net.URI; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Set; public class Jt808ProtocolEncoder extends BaseProtocolEncoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyMMddHHmmss").withZone(ZoneId.systemDefault()); + public Jt808ProtocolEncoder(Protocol protocol) { super(protocol); } @@ -103,8 +107,7 @@ public class Jt808ProtocolEncoder extends BaseProtocolEncoder { case Command.TYPE_ENGINE_RESUME: if (alternative) { data.writeByte(command.getType().equals(Command.TYPE_ENGINE_STOP) ? 0x01 : 0x00); - data.writeBytes(DataConverter.parseHex( - new SimpleDateFormat("yyMMddHHmmss").format(new Date()))); + data.writeBytes(DataConverter.parseHex(DATE_FORMAT.format(Instant.now()))); return decoder.formatMessage( Jt808ProtocolDecoder.MSG_OIL_CONTROL, id, false, data); } else { diff --git a/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java index 32d5a1991..b2bae2be8 100644 --- a/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java @@ -21,6 +21,7 @@ import org.traccar.BaseProtocolDecoder; import org.traccar.session.DeviceSession; import org.traccar.Protocol; import org.traccar.helper.DateBuilder; +import org.traccar.helper.DateUtil; import org.traccar.helper.Parser; import org.traccar.helper.PatternBuilder; import org.traccar.helper.UnitsConverter; @@ -30,17 +31,17 @@ import org.traccar.model.Position; import org.traccar.model.WifiAccessPoint; import java.net.SocketAddress; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.LinkedList; import java.util.List; -import java.util.TimeZone; import java.util.regex.Pattern; public class MictrackProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyMMddHHmmss").withZone(ZoneOffset.UTC); + public MictrackProtocolDecoder(Protocol protocol) { super(protocol); } @@ -58,12 +59,6 @@ public class MictrackProtocolDecoder extends BaseProtocolDecoder { .number("(dd)(dd)(dd)") // date (ddmmyy) .compile(); - private Date decodeTime(String data) throws ParseException { - DateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - return dateFormat.parse(data); - } - private String decodeAlarm(int event) { return switch (event) { case 0 -> Position.ALARM_POWER_ON; @@ -76,14 +71,14 @@ public class MictrackProtocolDecoder extends BaseProtocolDecoder { }; } - private void decodeLocation(Position position, String data) throws ParseException { + private void decodeLocation(Position position, String data) { int index = 0; String[] values = data.split("\\+"); position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++])); position.setValid(true); - position.setTime(decodeTime(values[index++])); + position.setTime(DateUtil.parse(DATE_FORMAT, values[index++])); position.setLatitude(Double.parseDouble(values[index++])); position.setLongitude(Double.parseDouble(values[index++])); position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++]))); @@ -118,11 +113,11 @@ public class MictrackProtocolDecoder extends BaseProtocolDecoder { } private void decodeNetwork( - Position position, String data, boolean hasWifi, boolean hasSsid, boolean hasCell) throws ParseException { + Position position, String data, boolean hasWifi, boolean hasSsid, boolean hasCell) { int index = 0; String[] values = data.split("\\+"); - getLastLocation(position, decodeTime(values[index++])); + getLastLocation(position, DateUtil.parse(DATE_FORMAT, values[index++])); Network network = new Network(); @@ -142,13 +137,13 @@ public class MictrackProtocolDecoder extends BaseProtocolDecoder { position.set(Position.KEY_BATTERY, Integer.parseInt(values[index++]) * 0.001); } - private void decodeStatus(Position position, String data) throws ParseException { + private void decodeStatus(Position position, String data) { int index = 0; String[] values = data.split("\\+"); position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++])); - getLastLocation(position, decodeTime(values[index++])); + getLastLocation(position, DateUtil.parse(DATE_FORMAT, values[index++])); index += 4; // fix values diff --git a/src/main/java/org/traccar/protocol/NoranProtocolDecoder.java b/src/main/java/org/traccar/protocol/NoranProtocolDecoder.java index f5faec4ed..54352bae9 100644 --- a/src/main/java/org/traccar/protocol/NoranProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/NoranProtocolDecoder.java @@ -24,16 +24,20 @@ import org.traccar.NetworkMessage; import org.traccar.Protocol; import org.traccar.helper.BitUtil; import org.traccar.helper.DateBuilder; +import org.traccar.helper.DateUtil; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; public class NoranProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()); + public NoranProtocolDecoder(Protocol protocol) { super(protocol); } @@ -129,8 +133,7 @@ public class NoranProtocolDecoder extends BaseProtocolDecoder { position.setDeviceId(deviceSession.getDeviceId()); if (newFormat) { - DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); - position.setTime(dateFormat.parse(buf.readSlice(17).toString(StandardCharsets.US_ASCII))); + position.setTime(DateUtil.parse(DATE_FORMAT, buf.readSlice(17).toString(StandardCharsets.US_ASCII))); buf.readByte(); } diff --git a/src/main/java/org/traccar/protocol/OrbcommProtocolPoller.java b/src/main/java/org/traccar/protocol/OrbcommProtocolPoller.java index 0f57bfb49..dd0201968 100644 --- a/src/main/java/org/traccar/protocol/OrbcommProtocolPoller.java +++ b/src/main/java/org/traccar/protocol/OrbcommProtocolPoller.java @@ -29,13 +29,15 @@ import org.traccar.config.Config; import org.traccar.config.Keys; import java.net.SocketAddress; -import java.text.DateFormat; -import java.text.SimpleDateFormat; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.Date; -import java.util.TimeZone; public class OrbcommProtocolPoller extends BaseProtocolPoller { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC); + private final String accessId; private final String password; private final String host; @@ -60,9 +62,7 @@ public class OrbcommProtocolPoller extends BaseProtocolPoller { encoder.addParam("access_id", accessId); encoder.addParam("password", password); - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - encoder.addParam("start_utc", dateFormat.format(startTime)); + encoder.addParam("start_utc", DATE_FORMAT.format(startTime.toInstant())); HttpRequest request = new DefaultFullHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, encoder.toString(), Unpooled.buffer()); diff --git a/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java b/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java index cf8ec7be7..01e1eab5e 100644 --- a/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/OsmAndProtocolDecoder.java @@ -39,14 +39,17 @@ import org.traccar.model.WifiAccessPoint; import java.io.StringReader; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.List; import java.util.Map; public class OsmAndProtocolDecoder extends BaseHttpProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()); + private double minAccuracy; public OsmAndProtocolDecoder(Protocol protocol) { @@ -118,8 +121,7 @@ public class OsmAndProtocolDecoder extends BaseHttpProtocolDecoder { if (value.contains("T")) { position.setTime(DateUtil.parseDate(value)); } else { - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - position.setTime(dateFormat.parse(value)); + position.setTime(DateUtil.parse(DATE_FORMAT, value)); } } break; diff --git a/src/main/java/org/traccar/protocol/Pt60ProtocolDecoder.java b/src/main/java/org/traccar/protocol/Pt60ProtocolDecoder.java index 94b549fe6..906f3b918 100644 --- a/src/main/java/org/traccar/protocol/Pt60ProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/Pt60ProtocolDecoder.java @@ -27,12 +27,16 @@ import org.traccar.model.Network; import org.traccar.model.Position; import java.net.SocketAddress; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.regex.Pattern; public class Pt60ProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyyMMddHHmmss").withZone(ZoneId.systemDefault()); + public Pt60ProtocolDecoder(Protocol protocol) { super(protocol); } @@ -63,7 +67,7 @@ public class Pt60ProtocolDecoder extends BaseProtocolDecoder { private void sendResponse(Channel channel, SocketAddress remoteAddress, String format, int type, String imei) { if (channel != null) { String message; - String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + String time = DATE_FORMAT.format(Instant.now()); if (format.equals("G")) { message = String.format("@G#@,V01,38,%s,@R#@", time); } else { diff --git a/src/main/java/org/traccar/protocol/PuiProtocolDecoder.java b/src/main/java/org/traccar/protocol/PuiProtocolDecoder.java index f10ff3fe7..54bffe084 100644 --- a/src/main/java/org/traccar/protocol/PuiProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/PuiProtocolDecoder.java @@ -21,15 +21,19 @@ import jakarta.json.JsonObject; import org.apache.kafka.common.utils.ByteBufferInputStream; import org.traccar.BaseMqttProtocolDecoder; import org.traccar.Protocol; +import org.traccar.helper.DateUtil; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; import org.traccar.session.DeviceSession; -import java.text.DateFormat; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; public class PuiProtocolDecoder extends BaseMqttProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(ZoneId.systemDefault()); + public PuiProtocolDecoder(Protocol protocol) { super(protocol); } @@ -51,8 +55,7 @@ public class PuiProtocolDecoder extends BaseMqttProtocolDecoder { position.setValid(true); - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); - position.setTime(dateFormat.parse(json.getString("ts"))); + position.setTime(DateUtil.parse(DATE_FORMAT, json.getString("ts"))); JsonObject location = json.getJsonObject("location"); position.setLatitude(location.getJsonNumber("lat").doubleValue()); diff --git a/src/main/java/org/traccar/protocol/S168ProtocolDecoder.java b/src/main/java/org/traccar/protocol/S168ProtocolDecoder.java index cf665c6ba..f157492a7 100644 --- a/src/main/java/org/traccar/protocol/S168ProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/S168ProtocolDecoder.java @@ -19,6 +19,7 @@ import io.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.session.DeviceSession; import org.traccar.Protocol; +import org.traccar.helper.DateUtil; import org.traccar.helper.UnitsConverter; import org.traccar.model.CellTower; import org.traccar.model.Network; @@ -26,12 +27,14 @@ import org.traccar.model.Position; import org.traccar.model.WifiAccessPoint; import java.net.SocketAddress; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.TimeZone; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; public class S168ProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyMMddHHmmss").withZone(ZoneOffset.UTC); + public S168ProtocolDecoder(Protocol protocol) { super(protocol); } @@ -69,9 +72,7 @@ public class S168ProtocolDecoder extends BaseProtocolDecoder { case "GDATA": position.setValid(values[index++].equals("A")); position.set(Position.KEY_SATELLITES, Integer.parseInt(values[index++])); - DateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - position.setTime(dateFormat.parse(values[index++])); + position.setTime(DateUtil.parse(DATE_FORMAT, values[index++])); position.setLatitude(Double.parseDouble(values[index++])); position.setLongitude(Double.parseDouble(values[index++])); position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[index++]))); diff --git a/src/main/java/org/traccar/protocol/SnapperProtocolDecoder.java b/src/main/java/org/traccar/protocol/SnapperProtocolDecoder.java index b1744442d..a11548adc 100644 --- a/src/main/java/org/traccar/protocol/SnapperProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/SnapperProtocolDecoder.java @@ -25,6 +25,7 @@ import org.traccar.NetworkMessage; import org.traccar.Protocol; import org.traccar.helper.BitUtil; import org.traccar.helper.Checksum; +import org.traccar.helper.DateUtil; import org.traccar.model.Position; import org.traccar.session.DeviceSession; @@ -32,13 +33,15 @@ import java.io.StringReader; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.TimeZone; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; public class SnapperProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("ddMMyyHHmmss").withZone(ZoneOffset.UTC); + public SnapperProtocolDecoder(Protocol protocol) { super(protocol); } @@ -126,9 +129,7 @@ public class SnapperProtocolDecoder extends BaseProtocolDecoder { position.setLongitude(-position.getLongitude()); } - DateFormat dateFormat = new SimpleDateFormat("ddMMyyHHmmss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - position.setTime(dateFormat.parse(json.getString("d") + json.getString("t").split("\\.")[0])); + position.setTime(DateUtil.parse(DATE_FORMAT, json.getString("d") + json.getString("t").split("\\.")[0])); String lat = json.getString("la"); position.setLatitude(Integer.parseInt(lat.substring(0, 2)) + Double.parseDouble(lat.substring(2)) / 60); diff --git a/src/main/java/org/traccar/protocol/StarcomProtocolDecoder.java b/src/main/java/org/traccar/protocol/StarcomProtocolDecoder.java index 1b0645d1c..f8afa6458 100644 --- a/src/main/java/org/traccar/protocol/StarcomProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/StarcomProtocolDecoder.java @@ -18,14 +18,19 @@ package org.traccar.protocol; import io.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.session.DeviceSession; +import org.traccar.helper.DateUtil; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; import java.net.SocketAddress; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; public class StarcomProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyy/MM/dd HH:mm:ss").withZone(ZoneId.systemDefault()); + public StarcomProtocolDecoder(StarcomProtocol protocol) { super(protocol); } @@ -52,7 +57,7 @@ public class StarcomProtocolDecoder extends BaseProtocolDecoder { } } case "gps_valid" -> position.setValid(Integer.parseInt(value) != 0); - case "datetime_actual" -> position.setTime(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").parse(value)); + case "datetime_actual" -> position.setTime(DateUtil.parse(DATE_FORMAT, value)); case "latitude" -> position.setLatitude(Double.parseDouble(value)); case "longitude" -> position.setLongitude(Double.parseDouble(value)); case "altitude" -> position.setAltitude(Double.parseDouble(value)); diff --git a/src/main/java/org/traccar/protocol/TelemaxProtocolDecoder.java b/src/main/java/org/traccar/protocol/TelemaxProtocolDecoder.java index f6f6f5379..a7a78ab91 100644 --- a/src/main/java/org/traccar/protocol/TelemaxProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TelemaxProtocolDecoder.java @@ -20,16 +20,21 @@ import org.traccar.BaseProtocolDecoder; import org.traccar.session.DeviceSession; import org.traccar.Protocol; import org.traccar.helper.BitUtil; +import org.traccar.helper.DateUtil; import org.traccar.model.Position; import java.net.SocketAddress; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.LinkedList; import java.util.List; public class TelemaxProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyMMddHHmmss").withZone(ZoneId.systemDefault()); + public TelemaxProtocolDecoder(Protocol protocol) { super(protocol); } @@ -94,10 +99,10 @@ public class TelemaxProtocolDecoder extends BaseProtocolDecoder { position.setLatitude((Integer.parseInt(readValue(sentence, index, 6), 16) - 5400000) / 30000.0); if (i == 0 | i == count - 1) { - time = new SimpleDateFormat("yyMMddHHmmss").parse(readValue(sentence, index, 12)); + time = DateUtil.parse(DATE_FORMAT, readValue(sentence, index, 12)); position.set(Position.KEY_STATUS, readValue(sentence, index, 8)); } else { - time = new Date(time.getTime() + interval * 1000); + time = new Date(time.getTime() + interval * 1000L); } position.setTime(time); diff --git a/src/main/java/org/traccar/protocol/TeraTrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/TeraTrackProtocolDecoder.java index 0cd93f5be..638dc434e 100644 --- a/src/main/java/org/traccar/protocol/TeraTrackProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TeraTrackProtocolDecoder.java @@ -20,6 +20,7 @@ import org.traccar.BaseProtocolDecoder; import org.traccar.session.DeviceSession; import org.traccar.NetworkMessage; import org.traccar.Protocol; +import org.traccar.helper.DateUtil; import org.traccar.helper.UnitsConverter; import org.traccar.model.Position; @@ -27,12 +28,14 @@ import jakarta.json.Json; import jakarta.json.JsonObject; import java.io.StringReader; import java.net.SocketAddress; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.TimeZone; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; public class TeraTrackProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC); + public TeraTrackProtocolDecoder(Protocol protocol) { super(protocol); } @@ -53,9 +56,7 @@ public class TeraTrackProtocolDecoder extends BaseProtocolDecoder { Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - position.setTime(dateFormat.parse(json.getString("DateTime"))); + position.setTime(DateUtil.parse(DATE_FORMAT, json.getString("DateTime"))); position.setValid(true); position.setLatitude(Double.parseDouble(json.getString("Latitude"))); diff --git a/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java b/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java index 946bb2162..5d051a393 100644 --- a/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TramigoProtocolDecoder.java @@ -30,9 +30,8 @@ import org.traccar.model.Position; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Calendar; import java.util.Date; import java.util.Locale; @@ -41,6 +40,11 @@ import java.util.regex.Pattern; public class TramigoProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT_WITH_SECONDS = DateTimeFormatter + .ofPattern("HH:mm:ss MMM d yyyy", Locale.ENGLISH).withZone(ZoneId.systemDefault()); + private static final DateTimeFormatter DATE_FORMAT_NO_SECONDS = DateTimeFormatter + .ofPattern("HH:mm MMM d yyyy", Locale.ENGLISH).withZone(ZoneId.systemDefault()); + public TramigoProtocolDecoder(Protocol protocol) { super(protocol); } @@ -217,7 +221,7 @@ public class TramigoProtocolDecoder extends BaseProtocolDecoder { } - private Position decode80(Channel channel, SocketAddress remoteAddress, ByteBuf buf) throws ParseException { + private Position decode80(Channel channel, SocketAddress remoteAddress, ByteBuf buf) { buf.readUnsignedByte(); // version id int index = buf.readUnsignedShort(); @@ -268,10 +272,9 @@ public class TramigoProtocolDecoder extends BaseProtocolDecoder { if (!matcher.find()) { return null; } - DateFormat dateFormat = new SimpleDateFormat( - matcher.group(2) != null ? "HH:mm:ss MMM d yyyy" : "HH:mm MMM d yyyy", Locale.ENGLISH); - position.setTime(DateUtil.correctYear( - dateFormat.parse(matcher.group(1) + " " + Calendar.getInstance().get(Calendar.YEAR)))); + DateTimeFormatter dateFormat = matcher.group(2) != null ? DATE_FORMAT_WITH_SECONDS : DATE_FORMAT_NO_SECONDS; + position.setTime(DateUtil.correctYear(DateUtil.parse( + dateFormat, matcher.group(1) + " " + Calendar.getInstance().get(Calendar.YEAR)))); if (sentence.contains("Ignition on detected")) { position.set(Position.KEY_IGNITION, true); diff --git a/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java b/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java index e3f7d011c..b5f84901b 100644 --- a/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TrvProtocolDecoder.java @@ -30,13 +30,17 @@ import org.traccar.model.Position; import org.traccar.model.WifiAccessPoint; import java.net.SocketAddress; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.regex.Pattern; import java.util.Set; public class TrvProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyyMMddHHmmss").withZone(ZoneId.systemDefault()); + private static final Set IGNORE_RESPONSE = Set.of( "AP12", "AP14", "AP33", "AP34", "AP40", "AP76", "AP77", "AP84", "AP85", "AP86", "AP87"); @@ -180,7 +184,7 @@ public class TrvProtocolDecoder extends BaseProtocolDecoder { if (channel != null) { String responseHeader = id + (char) (type.charAt(0) + 1) + type.substring(1); if (type.equals("AP00") && id.equals("IW")) { - String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + String time = DATE_FORMAT.format(Instant.now()); channel.writeAndFlush(new NetworkMessage(responseHeader + "," + time + ",0#", remoteAddress)); } else if (type.equals("AP14") && !id.equals("IW")) { channel.writeAndFlush(new NetworkMessage(responseHeader + ",0.000,0.000#", remoteAddress)); diff --git a/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java b/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java index 22074770b..29923ad63 100644 --- a/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/TzoneProtocolDecoder.java @@ -34,23 +34,22 @@ import org.traccar.model.Position; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; public class TzoneProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC); + public TzoneProtocolDecoder(Protocol protocol) { super(protocol); } private void sendResponse(Channel channel, SocketAddress remoteAddress, int index) { - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - String ack = String.format("@ACK,%d#", index); - String time = String.format("@UTC time:%s", dateFormat.format(new Date())); + String time = String.format("@UTC time:%s", DATE_FORMAT.format(Instant.now())); ByteBuf response = Unpooled.copiedBuffer(ack + time, StandardCharsets.US_ASCII); diff --git a/src/main/java/org/traccar/protocol/WristbandProtocolDecoder.java b/src/main/java/org/traccar/protocol/WristbandProtocolDecoder.java index f8cfe2b5e..2f99db6ff 100644 --- a/src/main/java/org/traccar/protocol/WristbandProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/WristbandProtocolDecoder.java @@ -22,6 +22,7 @@ import org.traccar.BaseProtocolDecoder; import org.traccar.session.DeviceSession; import org.traccar.NetworkMessage; import org.traccar.Protocol; +import org.traccar.helper.DateUtil; import org.traccar.helper.Parser; import org.traccar.helper.PatternBuilder; import org.traccar.helper.UnitsConverter; @@ -32,15 +33,20 @@ import org.traccar.model.WifiAccessPoint; import java.net.SocketAddress; import java.nio.charset.StandardCharsets; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.LinkedList; import java.util.List; import java.util.regex.Pattern; public class WristbandProtocolDecoder extends BaseProtocolDecoder { + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyyMMddHHmm").withZone(ZoneId.systemDefault()); + private static final DateTimeFormatter RESPONSE_DATE_FORMAT = DateTimeFormatter + .ofPattern("yyyy-MM-dd-HH-mm-ss").withZone(ZoneId.systemDefault()); + public WristbandProtocolDecoder(Protocol protocol) { super(protocol); } @@ -74,7 +80,7 @@ public class WristbandProtocolDecoder extends BaseProtocolDecoder { .text("\r\n") .compile(); - private Position decodePosition(DeviceSession deviceSession, String sentence) throws ParseException { + private Position decodePosition(DeviceSession deviceSession, String sentence) { Position position = new Position(getProtocolName()); position.setDeviceId(deviceSession.getDeviceId()); @@ -84,7 +90,7 @@ public class WristbandProtocolDecoder extends BaseProtocolDecoder { position.setValid(true); position.setLongitude(Double.parseDouble(values[0])); position.setLatitude(Double.parseDouble(values[1])); - position.setTime(new SimpleDateFormat("yyyyMMddHHmm").parse(values[2])); + position.setTime(DateUtil.parse(DATE_FORMAT, values[2])); position.setSpeed(UnitsConverter.knotsFromKph(Double.parseDouble(values[3]))); return position; @@ -135,7 +141,7 @@ public class WristbandProtocolDecoder extends BaseProtocolDecoder { } private List decodeMessage( - Channel channel, SocketAddress remoteAddress, String sentence) throws ParseException { + Channel channel, SocketAddress remoteAddress, String sentence) { Parser parser = new Parser(PATTERN, sentence); if (!parser.matches()) { @@ -157,7 +163,7 @@ public class WristbandProtocolDecoder extends BaseProtocolDecoder { switch (type) { case 90 -> sendResponse(channel, imei, version, type, getServer(channel, ',')); case 91 -> { - String time = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String time = RESPONSE_DATE_FORMAT.format(Instant.now()); sendResponse(channel, imei, version, type, time + "|" + getServer(channel, ',')); } case 1 -> {