bugfix: date-times were displayed @ UTC, not localtime
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -7,7 +7,6 @@ import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||
import static de.srsoftware.umbrella.messagebus.events.Event.EventType.MEMBER_ADDED;
|
||||
|
||||
import de.srsoftware.umbrella.core.constants.Field;
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||
import de.srsoftware.umbrella.core.model.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -7,6 +7,7 @@ import static de.srsoftware.tools.PathHandler.GET;
|
||||
import static de.srsoftware.tools.PathHandler.POST;
|
||||
import static de.srsoftware.tools.Strings.hex;
|
||||
import static de.srsoftware.umbrella.core.Errors.INVALID_URL;
|
||||
import static de.srsoftware.umbrella.core.constants.Constants.TIME_FORMATTER;
|
||||
import static de.srsoftware.umbrella.core.constants.Field.*;
|
||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.serverError;
|
||||
import static java.lang.System.Logger.Level.*;
|
||||
@@ -200,7 +201,7 @@ public class Util {
|
||||
plantumlJar = file;
|
||||
}
|
||||
|
||||
public static LocalDateTime dateTimeOf(long epocSecs){
|
||||
return LocalDateTime.ofInstant(Instant.ofEpochSecond(epocSecs), ZoneId.systemDefault());
|
||||
public static String dateTimeOf(long epochMilis){
|
||||
return LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilis), ZoneId.systemDefault()).format(TIME_FORMATTER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public class Constants {
|
||||
public static final String NO_CACHE = "no-cache";
|
||||
public static final String NONE = "none";
|
||||
public static final String TABLE_SETTINGS = "settings";
|
||||
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
|
||||
public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
public static final String UMBRELLA = "Umbrella";
|
||||
public static final String UTF8 = UTF_8.displayName();
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -22,7 +21,6 @@ import org.json.JSONObject;
|
||||
public class Envelope<T extends Message<?>> {
|
||||
private final T message;
|
||||
private final Set<User> receivers;
|
||||
private LocalDateTime time;
|
||||
private final long id;
|
||||
|
||||
public Envelope(long id, T message, User receiver){
|
||||
@@ -32,7 +30,6 @@ public class Envelope<T extends Message<?>> {
|
||||
public Envelope(long id, T message, Collection<? extends User> receivers) {
|
||||
this.message = message;
|
||||
this.receivers = new HashSet<>(receivers);
|
||||
time = LocalDateTime.now();
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@@ -60,12 +57,12 @@ public class Envelope<T extends Message<?>> {
|
||||
@Override
|
||||
public final boolean equals(Object o) {
|
||||
if (!(o instanceof Envelope<?> envelope)) return false;
|
||||
return message.equals(envelope.message) && time.equals(envelope.time);
|
||||
return message.equals(envelope.message) && id == envelope.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * message.hashCode() + time.hashCode();
|
||||
return message.hashCode();
|
||||
}
|
||||
|
||||
public long id(){
|
||||
@@ -84,15 +81,6 @@ public class Envelope<T extends Message<?>> {
|
||||
return receivers;
|
||||
}
|
||||
|
||||
public Envelope<T> time(LocalDateTime timestamp){
|
||||
this.time = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LocalDateTime time(){
|
||||
return time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return format("{0} (to: {1}), subject: {2}",getClass().getSimpleName(),receivers.stream().map(User::email).map(EmailAddress::toString).collect(Collectors.joining(", ")),message.subject());
|
||||
|
||||
@@ -10,12 +10,14 @@ public abstract class Message<T> {
|
||||
private final Collection<Attachment> attachments;
|
||||
private final T body, subject;
|
||||
private final UmbrellaUser sender;
|
||||
private long utcTime;
|
||||
|
||||
public Message(UmbrellaUser sender, T subject, T body, Collection<Attachment> attachments){
|
||||
this.sender = sender;
|
||||
this.subject = subject;
|
||||
this.body = body;
|
||||
this.attachments = attachments;
|
||||
this.utcTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public Collection<Attachment> attachments(){
|
||||
@@ -49,4 +51,13 @@ public abstract class Message<T> {
|
||||
public String toString() {
|
||||
return format("{0}(from: {1}), subject: {2}",getClass().getSimpleName(),sender,subject);
|
||||
}
|
||||
|
||||
public long utcTime() {
|
||||
return utcTime;
|
||||
}
|
||||
|
||||
public Message<T> utcTime(long newValue){
|
||||
utcTime = newValue;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ public class TranslatableMessage extends Message<Translatable> {
|
||||
}
|
||||
|
||||
public TranslatedMessage translate(String lang){
|
||||
return new TranslatedMessage(sender(),subject().translate(lang),body().translate(lang),attachments());
|
||||
var translated = new TranslatedMessage(sender(),subject().translate(lang),body().translate(lang),attachments());
|
||||
translated.utcTime(this.utcTime());
|
||||
return translated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ import jakarta.mail.internet.MimeMessage;
|
||||
import jakarta.mail.internet.MimeMultipart;
|
||||
import jakarta.mail.util.ByteArrayDataSource;
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.util.*;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
@@ -189,12 +191,12 @@ public class MessageSystem extends BaseHandler implements PostBox, EventListener
|
||||
|
||||
private boolean markRead(HttpExchange ex, UmbrellaUser user, String path) {
|
||||
try {
|
||||
var hash = Integer.parseInt(path);
|
||||
var envelope = queue.markRead(hash, user);
|
||||
var id = Integer.parseInt(path);
|
||||
var envelope = queue.markRead(id, user);
|
||||
if (envelope.isPresent()) return sendMessage(ex,user,envelope.get());
|
||||
return notFound(ex);
|
||||
} catch (NumberFormatException | IOException e) {
|
||||
throw invalidField(HASH,LONG);
|
||||
throw invalidField(ID,LONG);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,9 +223,9 @@ public class MessageSystem extends BaseHandler implements PostBox, EventListener
|
||||
|
||||
try {
|
||||
var envelopes = queue.getEnvelopesFor(receiver);
|
||||
envelopes.stream().forEach(combined::merge);
|
||||
envelopes.stream().map(Envelope::message).forEach(combined::merge);
|
||||
send(combined,date);
|
||||
envelopes.forEach(env -> queue.markRead(env.hashCode(),receiver));
|
||||
envelopes.forEach(env -> queue.markRead(env.id(),receiver));
|
||||
} catch (Exception ex){
|
||||
LOG.log(WARNING,"Failed to deliver mail ({0}) to {1}.",combined.subject(),receiver,ex);
|
||||
for (var message : combined.messages()) exceptions.computeIfAbsent(new Receiver(receiver,message), k -> new ArrayList<>()).add(ex);
|
||||
@@ -328,7 +330,7 @@ public class MessageSystem extends BaseHandler implements PostBox, EventListener
|
||||
|
||||
var sender = message.sender().name();
|
||||
var subject = message.subject();
|
||||
var time = envelope.time().format(TIME_FORMATTER);
|
||||
var time = Instant.ofEpochMilli(message.utcTime()).atZone(ZoneId.systemDefault()).toLocalDateTime().format(TIME_FORMATTER);
|
||||
var id = envelope.id();
|
||||
return new JSONObject(Map.of(SENDER,sender,SUBJECT,subject,TIMESTAMP,time,ID,id));
|
||||
}
|
||||
|
||||
@@ -14,11 +14,9 @@ import static de.srsoftware.umbrella.core.model.Translatable.t;
|
||||
import static de.srsoftware.umbrella.message.Constants.*;
|
||||
import static de.srsoftware.umbrella.message.model.Schedule.schedule;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static java.time.ZoneOffset.UTC;
|
||||
|
||||
import de.srsoftware.tools.jdbc.Query;
|
||||
import de.srsoftware.umbrella.core.BaseDb;
|
||||
import de.srsoftware.umbrella.core.Util;
|
||||
import de.srsoftware.umbrella.core.constants.Text;
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||
import de.srsoftware.umbrella.core.model.*;
|
||||
@@ -162,7 +160,7 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} INTEGER PRIMARY KEY, {2} VARCHAR(255) NOT N
|
||||
var messageId = rs.getLong(ID);
|
||||
var sender = userService().loadUser(rs.getLong(SENDER_USER_ID));
|
||||
var msg = new TranslatedMessage(sender,rs.getString(SUBJECT),rs.getString(BODY), attachments.get(messageId));
|
||||
var envelope = new Envelope<>(messageId, msg, user).time(Util.dateTimeOf(rs.getLong(TIMESTAMP)));
|
||||
var envelope = new Envelope<>(messageId, msg, user);
|
||||
envelopes.add(envelope);
|
||||
}
|
||||
rs.close();
|
||||
@@ -224,8 +222,8 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} INTEGER PRIMARY KEY, {2} VARCHAR(255) NOT N
|
||||
|
||||
@Override
|
||||
public void push(Envelope<TranslatedMessage> envelope) {
|
||||
var timestamp = envelope.time().toEpochSecond(UTC);
|
||||
var message = envelope.message();
|
||||
var timestamp = message.utcTime();
|
||||
var sender = message.sender().id();
|
||||
var subject = message.subject();
|
||||
var body = message.body();
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
/* © SRSoftware 2025 */
|
||||
package de.srsoftware.umbrella.message.model;
|
||||
|
||||
import static de.srsoftware.umbrella.core.Util.dateTimeOf;
|
||||
import static java.lang.System.Logger.Level.DEBUG;
|
||||
import static java.lang.System.Logger.Level.TRACE;
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
import de.srsoftware.umbrella.core.model.*;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
|
||||
public class CombinedMessage {
|
||||
@@ -22,7 +20,6 @@ public class CombinedMessage {
|
||||
private final List<Message<?>> mergedMessages = new ArrayList<>();
|
||||
private final Translatable subjectForCombinedMessage;
|
||||
private UmbrellaUser sender = null;
|
||||
private static DateTimeFormatter DT_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public CombinedMessage(Translatable subjectForCombinedMessage, User receiver){
|
||||
LOG.log(DEBUG,"Creating combined message for {0}…",receiver);
|
||||
@@ -31,9 +28,8 @@ public class CombinedMessage {
|
||||
this.lang = receiver.language();
|
||||
}
|
||||
|
||||
public void merge(Envelope<?> envelope) {
|
||||
LOG.log(TRACE,"Merging {0} into combined message…",envelope);
|
||||
var message = envelope.message();
|
||||
public void merge(Message<?> message) {
|
||||
LOG.log(TRACE,"Merging {0} into combined message…",message);
|
||||
|
||||
if (message instanceof TranslatableMessage tm) message = tm.translate(lang);
|
||||
var body = message.body();
|
||||
@@ -45,11 +41,11 @@ public class CombinedMessage {
|
||||
combinedSubject = subject;
|
||||
break;
|
||||
case 1:
|
||||
combinedBody.insert(0,format("# {0} @ {1}\n→ {2}:\n\n",sender,envelope.time().format(DT_FORMAT),subject)); // insert sender and subject of first message right before the body of the first message
|
||||
combinedBody.insert(0,format("# {0} @ {1}\n→ {2}:\n\n",sender, dateTimeOf(message.utcTime()),subject)); // insert sender and subject of first message right before the body of the first message
|
||||
combinedSubject = subjectForCombinedMessage.translate(lang);
|
||||
// no break here, we need to append the subject and content
|
||||
default:
|
||||
combinedBody.append("\n\n━━━━━━━━━━━━━━━━━━━━━\n\n# ").append(message.sender()).append(" @ ").append(envelope.time().format(DT_FORMAT)).append("\n→ ").append(subject).append(":\n\n");
|
||||
combinedBody.append("\n\n━━━━━━━━━━━━━━━━━━━━━\n\n# ").append(message.sender()).append(" @ ").append(dateTimeOf(message.utcTime())).append("\n→ ").append(subject).append(":\n\n");
|
||||
combinedBody.append(body);
|
||||
}
|
||||
if (message.attachments() != null) attachments.addAll(message.attachments());
|
||||
|
||||
Reference in New Issue
Block a user