diff --git a/scripts/initializr/common/src/main/java/com/codename1/initializr/model/GeneratorModel.java b/scripts/initializr/common/src/main/java/com/codename1/initializr/model/GeneratorModel.java index 27f89917f8f..e17d847771d 100644 --- a/scripts/initializr/common/src/main/java/com/codename1/initializr/model/GeneratorModel.java +++ b/scripts/initializr/common/src/main/java/com/codename1/initializr/model/GeneratorModel.java @@ -92,10 +92,16 @@ public static boolean isMavenLayoutChoiceOffered() { /// generated there. static final String BASTION_SINCE = "7.0.280"; + /// The first release whose ORM maps `java.time.Instant` entity fields, which + /// every other full-stack template's server stores its timestamps in. Against + /// an older release its backend does not compile, so it is neither offered nor + /// generated there. + static final String JAVA_TIME_ENTITIES_SINCE = "7.0.280"; + /// The first release a template can be generated against. static String templateSince(Template template) { return template == Template.BASTION ? BASTION_SINCE - : template == Template.REEL ? REEL_SINCE : FULL_STACK_SINCE; + : template == Template.REEL ? REEL_SINCE : JAVA_TIME_ENTITIES_SINCE; } /// The brand colour of the full-stack template as it ships: the `--brand` its diff --git a/scripts/initializr/common/src/main/resources/parley-modules.zip b/scripts/initializr/common/src/main/resources/parley-modules.zip index 5cdfc79667b..064091cef09 100644 Binary files a/scripts/initializr/common/src/main/resources/parley-modules.zip and b/scripts/initializr/common/src/main/resources/parley-modules.zip differ diff --git a/scripts/initializr/common/src/main/resources/savor-modules.zip b/scripts/initializr/common/src/main/resources/savor-modules.zip index f66519b68a5..c438df29fe5 100644 Binary files a/scripts/initializr/common/src/main/resources/savor-modules.zip and b/scripts/initializr/common/src/main/resources/savor-modules.zip differ diff --git a/scripts/initializr/common/src/main/resources/skirmish-modules.zip b/scripts/initializr/common/src/main/resources/skirmish-modules.zip index 66526040051..89390acd7ef 100644 Binary files a/scripts/initializr/common/src/main/resources/skirmish-modules.zip and b/scripts/initializr/common/src/main/resources/skirmish-modules.zip differ diff --git a/scripts/initializr/common/src/main/resources/wayline-modules.zip b/scripts/initializr/common/src/main/resources/wayline-modules.zip index dde1cb3a952..5df1bb7f48b 100644 Binary files a/scripts/initializr/common/src/main/resources/wayline-modules.zip and b/scripts/initializr/common/src/main/resources/wayline-modules.zip differ diff --git a/scripts/initializr/common/src/test/java/com/codename1/initializr/model/GeneratorModelMatrixTest.java b/scripts/initializr/common/src/test/java/com/codename1/initializr/model/GeneratorModelMatrixTest.java index 982382694c8..983fedfbda3 100644 --- a/scripts/initializr/common/src/test/java/com/codename1/initializr/model/GeneratorModelMatrixTest.java +++ b/scripts/initializr/common/src/test/java/com/codename1/initializr/model/GeneratorModelMatrixTest.java @@ -507,11 +507,14 @@ private void validateFullStackTemplate() throws Exception { true, false, ProjectOptions.PreviewLanguage.ENGLISH, ProjectOptions.JavaVersion.JAVA_8, null, ProjectOptions.BuildTool.MAVEN, ProjectOptions.ProjectType.APP_WITH_BACKEND); assertRefused(GeneratorModel.createForPluginVersion(IDE.INTELLIJ, Template.WAYLINE, "NoJava8", - "com.acme.nojava8", java8, FULL_STACK_VERSION), "Java 17", "A full-stack template is Java 17"); + "com.acme.nojava8", java8, WAYLINE_VERSION), "Java 17", "A full-stack template is Java 17"); // Bastion's app calls framework API newer than the other templates need. assertRefused(GeneratorModel.createForPluginVersion(IDE.INTELLIJ, Template.BASTION, "TooOld", "com.acme.tooold", mavenOptions(ProjectOptions.ProjectType.APP_WITH_BACKEND, false), FULL_STACK_VERSION), GeneratorModel.BASTION_SINCE, "Bastion must refuse a release before its own"); + assertRefused(GeneratorModel.createForPluginVersion(IDE.INTELLIJ, Template.WAYLINE, "OldTime", + "com.acme.oldtime", base, FULL_STACK_VERSION), GeneratorModel.JAVA_TIME_ENTITIES_SINCE, + "Wayline's server stores java.time entity fields, which a release before its gate cannot map"); ProjectOptions forced = java8.withBuild(ProjectOptions.BuildTool.GRADLE, ProjectOptions.ProjectType.APP) .forFullStack(); assertTrue(!forced.isGradle() && forced.projectType == ProjectOptions.ProjectType.APP_WITH_BACKEND @@ -519,7 +522,7 @@ private void validateFullStackTemplate() throws Exception { "forFullStack should settle the build, the project type and the Java level"); String themePath = "common/src/main/css/theme.css"; - String stock = getText(mavenEntries(FULL_STACK_VERSION, Template.WAYLINE, IDE.INTELLIJ, "StockApp", + String stock = getText(mavenEntries(WAYLINE_VERSION, Template.WAYLINE, IDE.INTELLIJ, "StockApp", "com.acme.stock", base), themePath); String brand = Integer.toHexString(GeneratorModel.FULL_STACK_BRAND); assertContains(stock, "--brand: #" + brand + ";", @@ -529,7 +532,7 @@ private void validateFullStackTemplate() throws Exception { "The stock scheme must leave the stylesheet exactly as the template has it"); byte[] icon = new byte[] {(byte) 0x89, 'P', 'N', 'G', 1, 2, 3}; - Map styled = mavenEntries(FULL_STACK_VERSION, Template.WAYLINE, IDE.INTELLIJ, "StyledApp", + Map styled = mavenEntries(WAYLINE_VERSION, Template.WAYLINE, IDE.INTELLIJ, "StyledApp", "com.acme.styled", base.withScheme(0x0f766e, false).withIcon(icon)); String css = getText(styled, themePath); assertContains(css, "--brand: #0f766e;", "The chosen brand colour should be the theme's"); @@ -545,7 +548,7 @@ private void validateFullStackTemplate() throws Exception { "Choosing a scheme should rewrite declarations and add no rules"); assertTrue(java.util.Arrays.equals(icon, styled.get("common/icon.png")), "The chosen icon should replace the stock one"); - assertFalse(java.util.Arrays.equals(icon, mavenEntries(FULL_STACK_VERSION, Template.WAYLINE, IDE.INTELLIJ, + assertFalse(java.util.Arrays.equals(icon, mavenEntries(WAYLINE_VERSION, Template.WAYLINE, IDE.INTELLIJ, "StockApp", "com.acme.stock", base).get("common/icon.png")), "Without a chosen icon the project keeps the stock one"); @@ -576,6 +579,8 @@ private void assertRefused(GeneratorModel model, String expectedReason, String m private static final String LAYOUTS_VERSION = "7.0.275"; /// The version the full-stack combinations are generated for. private static final String FULL_STACK_VERSION = GeneratorModel.FULL_STACK_SINCE; + /// The version Wayline is generated for: its own gate, past the contract module's. + private static final String WAYLINE_VERSION = GeneratorModel.templateSince(Template.WAYLINE); /// The streaming template needs a newer core than the other complete apps: /// below its own gate it is refused, and the page does not list it. diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/Rows.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/Rows.java index 987454aa527..46069737430 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/Rows.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/Rows.java @@ -18,7 +18,7 @@ */ package com.codenameone.examples.parley; - +import java.time.Instant; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -39,6 +39,17 @@ public static long number(Object value) { return value instanceof Number ? ((Number) value).longValue() : 0L; } + /// A timestamp column as epoch milliseconds. Anything but an `Instant` + /// means the query selected something other than a timestamp, which is + /// a bug to see rather than a zero to chart. + public static long millis(Object value) { + if (value instanceof Instant) { + return ((Instant) value).toEpochMilli(); + } + throw new IllegalStateException("Expected a java.time.Instant column but got " + + (value == null ? "null" : value.getClass().getName())); + } + /// A column as text; empty for null. public static String text(Object value) { return value == null ? "" : String.valueOf(value); diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/AccountCleanup.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/AccountCleanup.java index e505e65c17a..0efb76745b8 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/AccountCleanup.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/AccountCleanup.java @@ -38,6 +38,7 @@ import com.codenameone.examples.parley.repository.ReportRepository; import java.io.IOException; +import java.time.Instant; import java.util.List; /// What closing an account does to the rows other parts of the server keep @@ -118,7 +119,7 @@ public void removeEverythingOf(String username) throws IOException { pushDevices.deleteByUsername(username); // The other side of a live call holds a line too, and nothing else // would ever free it once the call record is gone. - List live = calls.liveOf(username); + List live = calls.liveOf(username, Instant.EPOCH); for (int iter = 0; iter < live.size(); iter++) { lines.deleteByCallId(live.get(iter).getId()); } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/Accounts.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/Accounts.java index b82015a1006..897d74e3be7 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/Accounts.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/Accounts.java @@ -40,6 +40,7 @@ import com.codenameone.examples.parley.repository.ProfileRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -156,7 +157,7 @@ void create(String username, String password, String displayName, String phone, profile.setDisplayName(displayName); profile.setPhone(phone); profile.setPhoneVerified(phoneVerified); - profile.setCreatedAt(openedAt); + profile.setCreatedAt(Instant.ofEpochMilli(openedAt)); profile.setLanguage(""); profiles.insert(profile); } @@ -393,7 +394,7 @@ private void retire(String username) throws IOException { if (!closed.existsById(hash)) { ClosedAccount row = new ClosedAccount(); row.setUsernameHash(hash); - row.setClosedAt(System.currentTimeMillis()); + row.setClosedAt(Instant.now()); closed.insert(row); } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/Moderation.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/Moderation.java index 826c2485d4d..3004e49d4ab 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/Moderation.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/Moderation.java @@ -26,6 +26,7 @@ import com.codenameone.examples.parley.repository.ModerationEventRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -58,8 +59,8 @@ public void record(String username, String by, String action, String reason) // came with it -- would otherwise be listed in either order. The later // one is stamped after the one before it, so the list is the order in // which things were done. - Long newest = events.newest(username); - long after = newest == null ? 0L : newest.longValue() + 1L; + Instant newest = events.newest(username); + long after = newest == null ? 0L : newest.toEpochMilli() + 1L; record(username, by, action, reason, Math.max(System.currentTimeMillis(), after)); } @@ -72,7 +73,7 @@ public void record(String username, String by, String action, String reason, lon ModerationEvent event = new ModerationEvent(); event.setId(Ids.next()); event.setUsername(username); - event.setCreatedAt(at); + event.setCreatedAt(Instant.ofEpochMilli(at)); event.setActor(by); event.setAction(action); event.setReason(why.length() > 255 ? why.substring(0, 255) : why); @@ -86,7 +87,7 @@ public List events(String username) throws IOException { List out = new ArrayList(); for (int iter = 0; iter < rows.size(); iter++) { ModerationEvent row = rows.get(iter); - out.add(new ModerationEventDto(row.getCreatedAt(), row.getActor(), row.getAction(), + out.add(new ModerationEventDto(row.getCreatedAt().toEpochMilli(), row.getActor(), row.getAction(), row.getReason())); } return out; diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/PhoneVerification.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/PhoneVerification.java index 63106e3db47..8af67ae0050 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/PhoneVerification.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/account/PhoneVerification.java @@ -31,6 +31,7 @@ import com.codenameone.examples.parley.sms.SmsSender; import java.io.IOException; +import java.time.Instant; /// Proves an account's phone number by texting it a code. /// @@ -72,7 +73,7 @@ public PhoneChallengeDto start(String username) throws IOException { UserDto user = accounts.describe(username); String code = newCode(); String codeHash = hash(username, code); - store(username, codeHash, System.currentTimeMillis()); + store(username, codeHash, Instant.now()); try { sms.send(user.phone(), "Your Parley code is " + code); } catch (IOException failed) { @@ -98,20 +99,20 @@ public PhoneChallengeDto start(String username) throws IOException { /// one is kept, so at most two codes are live, and only one whose guesses /// were not used up. @Transactional - void store(String username, String codeHash, long now) throws IOException { + void store(String username, String codeHash, Instant now) throws IOException { // Before the code is read: two requests for one account take turns, // so the second finds the code the first just stored and is told to // wait. Otherwise both pass the check below and both send a text. accounts.hold(username); PhoneCode pending = codes.findById(username); - if (pending != null && now - pending.getSentAt() < RESEND_SECONDS * 1000L) { + if (pending != null && pending.getSentAt().plusSeconds(RESEND_SECONDS).isAfter(now)) { throw new ResponseStatusException(429, "Wait a moment before asking for another code"); } boolean first = pending == null; if (first) { pending = new PhoneCode(); pending.setUsername(username); - } else if (pending.getExpiresAt() >= now && pending.getAttempts() < MAX_ATTEMPTS) { + } else if (!pending.getExpiresAt().isBefore(now) && pending.getAttempts() < MAX_ATTEMPTS) { // With the guesses it has used: asking for another code must not // buy the old one a fresh set. pending.setPreviousHash(pending.getCodeHash()); @@ -119,11 +120,11 @@ void store(String username, String codeHash, long now) throws IOException { pending.setPreviousAttempts(pending.getAttempts()); } else { pending.setPreviousHash(""); - pending.setPreviousExpiresAt(0L); + pending.setPreviousExpiresAt(Instant.EPOCH); pending.setPreviousAttempts(0); } pending.setCodeHash(codeHash); - pending.setExpiresAt(now + CODE_SECONDS * 1000L); + pending.setExpiresAt(now.plusSeconds(CODE_SECONDS)); pending.setAttempts(0); pending.setSentAt(now); if (first) { @@ -148,7 +149,7 @@ void discard(String username, String codeHash) throws IOException { return; } if (pending.getPreviousHash().length() == 0 - || pending.getPreviousExpiresAt() < System.currentTimeMillis()) { + || pending.getPreviousExpiresAt().isBefore(Instant.now())) { codes.deleteById(username); return; } @@ -156,9 +157,9 @@ void discard(String username, String codeHash) throws IOException { pending.setExpiresAt(pending.getPreviousExpiresAt()); pending.setAttempts(pending.getPreviousAttempts()); pending.setPreviousHash(""); - pending.setPreviousExpiresAt(0L); + pending.setPreviousExpiresAt(Instant.EPOCH); pending.setPreviousAttempts(0); - pending.setSentAt(0L); + pending.setSentAt(Instant.EPOCH); } /// Checks the code the user typed. Answers 400 for a wrong or expired one @@ -186,7 +187,7 @@ boolean guess(String username, String code) throws IOException { // row the other has. accounts.hold(username); PhoneCode pending = codes.findById(username); - if (pending == null || pending.getExpiresAt() < System.currentTimeMillis()) { + if (pending == null || pending.getExpiresAt().isBefore(Instant.now())) { throw new ResponseStatusException(400, "That code has expired. Ask for a new one"); } if (pending.getAttempts() >= MAX_ATTEMPTS) { @@ -222,7 +223,7 @@ boolean guess(String username, String code) throws IOException { boolean previous = Crypto.equalsConstantTime(given, pending.getPreviousHash().getBytes("UTF-8")) && pending.getPreviousHash().length() > 0 - && pending.getPreviousExpiresAt() >= System.currentTimeMillis() + && !pending.getPreviousExpiresAt().isBefore(Instant.now()) && counted != null && counted.getPreviousAttempts() <= MAX_ATTEMPTS; if (!current && !previous) { return false; diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/admin/Statistics.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/admin/Statistics.java index 37106cf12a8..3530fd69057 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/admin/Statistics.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/admin/Statistics.java @@ -40,6 +40,7 @@ import com.codenameone.examples.parley.repository.ReportRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -93,8 +94,8 @@ public AdminStatsDto dashboard() throws IOException { (int) conversations.count(), (int) (conversations.countByKind(Conversations.GROUP) + conversations.countByKind(Conversations.CHANNEL)), - (int) messages.countBySentAtGreaterThanEqual(today), - (int) calls.countByStartedAtGreaterThanEqual(today), + (int) messages.countBySentAtGreaterThanEqual(Instant.ofEpochMilli(today)), + (int) calls.countByStartedAtGreaterThanEqual(Instant.ofEpochMilli(today)), (int) reports.countByStatus(OPEN), (int) bridges.count()); } @@ -113,8 +114,8 @@ public StatsSeriesDto series(int days) throws IOException { active.add(new HashSet<>()); } int[] byHour = new int[24]; - for (Object[] row : messages.since(since)) { - long at = Rows.number(row[0]); + for (Object[] row : messages.since(Instant.ofEpochMilli(since))) { + long at = Rows.millis(row[0]); byHour[(int) (at % Days.MILLIS / 3600000L)]++; int index = index(at, since, span); if (index >= 0) { @@ -122,14 +123,14 @@ public StatsSeriesDto series(int days) throws IOException { active.get(index).add(Rows.text(row[1])); } } - for (Long at : calls.startedSince(since)) { - int index = index(Rows.number(at), since, span); + for (Instant at : calls.startedSince(Instant.ofEpochMilli(since))) { + int index = index(Rows.millis(at), since, span); if (index >= 0) { dayCalls[index]++; } } - for (Long at : profiles.signUps(since)) { - int index = index(Rows.number(at), since, span); + for (Instant at : profiles.signUps(Instant.ofEpochMilli(since))) { + int index = index(Rows.millis(at), since, span); if (index >= 0) { dayUsers[index]++; } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/bridge/Bridges.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/bridge/Bridges.java index 8e1369fdebf..e592d2c6468 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/bridge/Bridges.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/bridge/Bridges.java @@ -39,6 +39,7 @@ import com.codenameone.examples.parley.repository.MembershipRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -134,7 +135,7 @@ public BridgeLinkDto link(String username, BridgeRequestDto request) throws IOEx link.setExternalChat(chat); link.setLabel(Text.optional(request.label(), 80, "the link's name")); link.setCreatedBy(username); - link.setCreatedAt(System.currentTimeMillis()); + link.setCreatedAt(Instant.now()); links.save(link); conversations.announce(row.getId(), "This conversation is now bridged to " + name(bridge.network()) + ". Messages here are no longer end-to-end encrypted."); @@ -174,8 +175,8 @@ public void incoming(String network, String externalChat, String senderName, Str return; } long now = System.currentTimeMillis(); - events.deleteByReceivedAtLessThan(now - EVENT_MEMORY_MILLIS); - events.insert(new BridgeEvent(key, now)); + events.deleteByReceivedAtLessThan(Instant.ofEpochMilli(now - EVENT_MEMORY_MILLIS)); + events.insert(new BridgeEvent(key, Instant.ofEpochMilli(now))); } BridgeLink link = links.findByNetworkAndExternalChat(network, externalChat); if (link == null) { @@ -232,6 +233,6 @@ static String name(String network) { static BridgeLinkDto toDto(BridgeLink row) { return new BridgeLinkDto(row.getId(), row.getConversationId(), row.getNetwork(), - row.getExternalChat(), row.getLabel(), row.getCreatedAt()); + row.getExternalChat(), row.getLabel(), row.getCreatedAt().toEpochMilli()); } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/call/Calls.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/call/Calls.java index 27dee836f85..f22939baf1a 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/call/Calls.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/call/Calls.java @@ -52,6 +52,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; @@ -173,11 +174,11 @@ public CallDto start(String username, CallStartDto request, boolean busy) throws row.setCallee(callee); row.setCalleeDevice(""); row.setVideo(request.video()); - row.setStartedAt(now); + row.setStartedAt(Instant.ofEpochMilli(now)); boolean blocked = blocked(username, callee); if (busy || lines.findById(callee) != null) { row.setState(BUSY); - row.setEndedAt(now); + row.setEndedAt(Instant.ofEpochMilli(now)); } else { row.setState(RINGING); } @@ -235,7 +236,7 @@ public void ring(CallDto call) throws IOException { /// where it learns who is calling and that the call is still live. @Transactional(readOnly = true) public void ringDevice(String username, String device) throws IOException { - for (CallRecord row : calls.liveOf(username)) { + for (CallRecord row : calls.liveOf(username, Instant.EPOCH)) { if (username.equals(row.getCallee()) && RINGING.equals(row.getState()) && !blocked(row.getCaller(), row.getCallee())) { live.toDevice(device, frame(row, "ring")); @@ -262,7 +263,7 @@ public CallDto signal(String username, String id, CallSignalDto signal) throws I if (signal.payload() != null && signal.payload().length() > MAX_PAYLOAD) { throw new ResponseStatusException(413, "That signal is too long"); } - if (row.getEndedAt() != 0) { + if (!row.getEndedAt().equals(Instant.EPOCH)) { // A late candidate for a call that is over is not an error the // app can do anything about. return toDto(row); @@ -291,7 +292,7 @@ public CallDto signal(String username, String id, CallSignalDto signal) throws I remember(row, signal.payload(), false); } else if (ACCEPT.equals(type) && !caller && RINGING.equals(row.getState())) { row.setState(ACCEPTED); - row.setAnsweredAt(now); + row.setAnsweredAt(Instant.ofEpochMilli(now)); row.setCalleeDevice(device); // The callee's other devices are still ringing. String ringId = uuid(row.getId()); @@ -377,14 +378,14 @@ public IceConfigDto ice(String username) { @Transactional(rollbackFor = IOException.class) public void reap() throws IOException { long now = System.currentTimeMillis(); - for (CallRecord row : calls.openSince(now - RING_MILLIS)) { + for (CallRecord row : calls.openSince(Instant.ofEpochMilli(now - RING_MILLIS), Instant.EPOCH)) { if (RINGING.equals(row.getState())) { end(row, MISSED, now); Map frame = frame(row, "signal"); List to = blocked(row.getCaller(), row.getCallee()) ? Arrays.asList(row.getCaller()) : Arrays.asList(row.getCaller(), row.getCallee()); afterCommit(() -> live.toUsers(to, frame)); - } else if (row.getAnsweredAt() < now - STALE_MILLIS) { + } else if (row.getAnsweredAt().toEpochMilli() < now - STALE_MILLIS) { end(row, ENDED, now); // Both apps still hold the call; without this they keep it // open and turn every later call away as busy. @@ -449,7 +450,7 @@ private Map replayed(CallRecord row, String type, String payload private void end(CallRecord row, String state, long now) { boolean ringing = RINGING.equals(row.getState()); row.setState(state); - row.setEndedAt(now); + row.setEndedAt(Instant.ofEpochMilli(now)); lines.deleteByCallId(row.getId()); if (setups.findById(row.getId()) != null) { setups.deleteById(row.getId()); @@ -548,7 +549,7 @@ private static List split(String urls) { static CallDto toDto(CallRecord row) { return new CallDto(row.getId(), row.getConversationId(), row.getCaller(), - row.getCallee(), row.isVideo(), row.getState(), row.getStartedAt(), - row.getAnsweredAt(), row.getEndedAt(), uuid(row.getId())); + row.getCallee(), row.isVideo(), row.getState(), row.getStartedAt().toEpochMilli(), + row.getAnsweredAt().toEpochMilli(), row.getEndedAt().toEpochMilli(), uuid(row.getId())); } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Conversations.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Conversations.java index 7df3428193e..f5dcea7ae50 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Conversations.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Conversations.java @@ -51,6 +51,7 @@ import com.codenameone.examples.parley.repository.ProfileRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; @@ -426,7 +427,7 @@ private void depart(Conversation row, Membership mine) throws IOException { for (int iter = 0; iter < rest.size(); iter++) { Membership each = rest.get(iter); if (heir == null || rank(each) > rank(heir) - || rank(each) == rank(heir) && each.getJoinedAt() < heir.getJoinedAt()) { + || rank(each) == rank(heir) && each.getJoinedAt().isBefore(heir.getJoinedAt())) { heir = each; } } @@ -462,8 +463,8 @@ public InviteDto invite(String username, String id) throws IOException { link.setCode(Ids.next()); link.setConversationId(id); link.setCreatedBy(username); - link.setCreatedAt(now); - link.setExpiresAt(now + INVITE_LIFE); + link.setCreatedAt(Instant.ofEpochMilli(now)); + link.setExpiresAt(Instant.ofEpochMilli(now + INVITE_LIFE)); invites.insert(link); return toDto(link, row, members.countByConversationId(id)); } @@ -496,8 +497,8 @@ public ConversationDto join(String username, String code) throws IOException { private InviteLink link(String code) { InviteLink link = code == null ? null : invites.findById(code); - if (link == null || link.getExpiresAt() > 0 - && link.getExpiresAt() < System.currentTimeMillis()) { + if (link == null || link.getExpiresAt().isAfter(Instant.EPOCH) + && link.getExpiresAt().isBefore(Instant.now())) { throw new ResponseStatusException(404, "That invite link does not work any more"); } return link; @@ -519,12 +520,12 @@ public ConversationDto savePhoto(String username, String id, PhotoDto photo) stored = new ConversationPhoto(); stored.setConversationId(id); stored.setContentType(photo.contentType()); - stored.setUpdatedAt(System.currentTimeMillis()); + stored.setUpdatedAt(Instant.now()); stored.setData(data); photos.insert(stored); } else { stored.setContentType(photo.contentType()); - stored.setUpdatedAt(System.currentTimeMillis()); + stored.setUpdatedAt(Instant.now()); stored.setData(data); } row.setHasPhoto(true); @@ -559,8 +560,8 @@ private static Conversation conversation(String kind, String title, String by, l row.setKind(kind); row.setTitle(title); row.setCreatedBy(by); - row.setCreatedAt(now); - row.setLastActivityAt(now); + row.setCreatedAt(Instant.ofEpochMilli(now)); + row.setLastActivityAt(Instant.ofEpochMilli(now)); // direct_key is unique, so it is what keeps two people to one direct // chat even when both start it at once: the second insert fails rather // than splitting their history. Every other conversation has a key of @@ -575,7 +576,7 @@ private void join(String id, String username, String role, long now) { row.setConversationId(id); row.setUsername(username); row.setRole(role); - row.setJoinedAt(now); + row.setJoinedAt(Instant.ofEpochMilli(now)); members.insert(row); } @@ -683,11 +684,11 @@ ConversationDto describe(Conversation row, Membership mine) { return new ConversationDto(row.getId(), row.getKind(), title, row.getAbout(), out, mine.getRole(), mine.isMuted(), mine.isArchived(), mine.isPinned(), row.getDisappearingSeconds(), row.isAdminsOnly(), bridge(row.getId()), - row.getLastActivityAt(), row.isHasPhoto()); + row.getLastActivityAt().toEpochMilli(), row.isHasPhoto()); } private static InviteDto toDto(InviteLink link, Conversation row, long count) { return new InviteDto(link.getCode(), row.getId(), row.getTitle(), (int) count, - link.getExpiresAt()); + link.getExpiresAt().toEpochMilli()); } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Fanout.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Fanout.java index b446c6a3c51..628cb1d7694 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Fanout.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Fanout.java @@ -35,6 +35,7 @@ import com.codenameone.examples.parley.domain.Membership; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -176,8 +177,8 @@ static Envelope envelope(String messageId, String conversationId, String sender, row.setKind(kind); row.setHeader(header == null ? "" : header); row.setPayload(payload); - row.setSentAt(sentAt); - row.setExpiresAt(expiresAt); + row.setSentAt(Instant.ofEpochMilli(sentAt)); + row.setExpiresAt(Instant.ofEpochMilli(expiresAt)); return row; } @@ -194,8 +195,8 @@ private void send(List batch) { frame.put("kind", row.getKind()); frame.put("header", row.getHeader()); frame.put("ciphertext", Base64.encode(row.getPayload())); - frame.put("sentAt", Long.valueOf(row.getSentAt())); - frame.put("expiresAt", Long.valueOf(row.getExpiresAt())); + frame.put("sentAt", Long.valueOf(row.getSentAt().toEpochMilli())); + frame.put("expiresAt", Long.valueOf(row.getExpiresAt().toEpochMilli())); live.toDevice(row.getRecipientDevice(), frame); } } @@ -203,6 +204,6 @@ private void send(List batch) { static EnvelopeDto toDto(Envelope row) { return new EnvelopeDto(row.getId(), row.getMessageId(), row.getConversationId(), row.getSender(), row.getSenderDevice(), row.getKind(), row.getHeader(), - Base64.encode(row.getPayload()), row.getSentAt(), row.getExpiresAt()); + Base64.encode(row.getPayload()), row.getSentAt().toEpochMilli(), row.getExpiresAt().toEpochMilli()); } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Media.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Media.java index 2bf509e5020..f59ada5dae9 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Media.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Media.java @@ -30,6 +30,7 @@ import com.codenameone.examples.parley.repository.MediaBlobRepository; import java.io.IOException; +import java.time.Instant; /// Encrypted attachments. /// @@ -68,7 +69,7 @@ public MediaRefDto upload(String username, MediaUploadDto media) throws IOExcept // day's bytes are capped as well, well past what anyone sharing // photos and voice notes uploads. long now = System.currentTimeMillis(); - Long stored = blobs.storedSince(username, now - DAY_MILLIS); + Long stored = blobs.storedSince(username, Instant.ofEpochMilli(now - DAY_MILLIS)); if ((stored == null ? 0L : stored.longValue()) + data.length > DAILY_BYTES) { throw new ResponseStatusException(429, "You have uploaded too much today"); } @@ -76,7 +77,7 @@ public MediaRefDto upload(String username, MediaUploadDto media) throws IOExcept row.setId(Ids.next()); row.setOwner(username); row.setSize(data.length); - row.setCreatedAt(now); + row.setCreatedAt(Instant.ofEpochMilli(now)); row.setData(data); blobs.insert(row); return new MediaRefDto(row.getId(), data.length); diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Messages.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Messages.java index c7e0a90bcef..bfc63f12ce1 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Messages.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/chat/Messages.java @@ -49,6 +49,7 @@ import com.codenameone.examples.parley.repository.ProfileRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashSet; import java.util.HashMap; @@ -151,7 +152,7 @@ public SendResultDto send(String username, OutgoingDto message) throws IOExcepti logId = Ids.sha256(username + "/" + clientId); MessageLog seen = log.findById(logId); if (seen != null) { - return new SendResultDto(seen.getMessageId(), seen.getSentAt(), + return new SendResultDto(seen.getMessageId(), seen.getSentAt().toEpochMilli(), new ArrayList(), new ArrayList()); } } @@ -236,7 +237,7 @@ public SendResultDto send(String username, OutgoingDto message) throws IOExcepti fanout.deliver(batch, wake, group); if (MESSAGE.equals(kind)) { record(logId, messageId, id, username, kind, now); - conversationRows.touched(id, now); + conversationRows.touched(id, Instant.ofEpochMilli(now)); } return new SendResultDto(messageId, now, missing, stale); } @@ -258,7 +259,7 @@ private SendResultDto sendPlain(String username, OutgoingDto message, Conversati String messageId = fanout.plain(row.getId(), username, message.senderDevice(), MESSAGE, to, text, expiresAt, group); record(logId, messageId, row.getId(), username, kind, now); - conversationRows.touched(row.getId(), now); + conversationRows.touched(row.getId(), Instant.ofEpochMilli(now)); Profile profile = profiles.findById(username); relays.posted(row.getId(), username, profile == null ? username : profile.getDisplayName(), text); @@ -278,7 +279,7 @@ public String post(String conversationId, String sender, String text) throws IOE !Conversations.DIRECT.equals(row.getKind())); record(Ids.sha256(sender + "/" + messageId), messageId, conversationId, sender, MESSAGE, now); - conversationRows.touched(conversationId, now); + conversationRows.touched(conversationId, Instant.ofEpochMilli(now)); return messageId; } @@ -314,10 +315,10 @@ public KeyCountDto ack(String username, String device, AckDto ack) { @Transactional public void reap() { long now = System.currentTimeMillis(); - envelopes.expire(now); - envelopes.deleteBySentAtLessThan(now - UNCLAIMED); - media.deleteByCreatedAtLessThan(now - UNCLAIMED); - log.deleteBySentAtLessThan(now - 90L * 24 * 60 * 60 * 1000); + envelopes.expire(Instant.ofEpochMilli(now), Instant.EPOCH); + envelopes.deleteBySentAtLessThan(Instant.ofEpochMilli(now - UNCLAIMED)); + media.deleteByCreatedAtLessThan(Instant.ofEpochMilli(now - UNCLAIMED)); + log.deleteBySentAtLessThan(Instant.ofEpochMilli(now - 90L * 24 * 60 * 60 * 1000)); } private void record(String logId, String messageId, String conversationId, String sender, @@ -331,7 +332,7 @@ private void record(String logId, String messageId, String conversationId, Strin row.setConversationId(conversationId); row.setSender(sender); row.setKind(kind); - row.setSentAt(now); + row.setSentAt(Instant.ofEpochMilli(now)); log.insert(row); } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/contact/Contacts.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/contact/Contacts.java index 5330ec1106a..c17bdd6739f 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/contact/Contacts.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/contact/Contacts.java @@ -45,6 +45,7 @@ import com.codenameone.examples.parley.repository.ReportRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -146,7 +147,7 @@ public ContactDto block(String viewer, String username) throws IOException { row.setId(id); row.setBlocker(viewer); row.setBlocked(username); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); blocks.insert(row); } return view(viewer, profile, peers(viewer)); @@ -185,7 +186,7 @@ public ReportViewDto report(String reporter, ReportDto report) throws IOExceptio row.setConversationId(Text.optional(report.conversationId(), 32, "the conversation")); row.setReason(Text.required(report.reason(), 255, "why you are reporting them")); row.setEvidence(Text.optional(report.evidence(), 4000, "the messages you attach")); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); row.setStatus("OPEN"); reports.insert(row); java.util.Map frame = new java.util.LinkedHashMap(); @@ -217,7 +218,7 @@ private List peers(String username) { public static ReportViewDto toDto(Report row) { return new ReportViewDto(row.getId(), row.getReporter(), row.getSubject(), - row.getConversationId(), row.getReason(), row.getEvidence(), row.getCreatedAt(), + row.getConversationId(), row.getReason(), row.getEvidence(), row.getCreatedAt().toEpochMilli(), row.getStatus()); } @@ -235,12 +236,12 @@ public void savePhoto(String username, PhotoDto photo) throws IOException { row = new ProfilePhoto(); row.setUsername(username); row.setContentType(photo.contentType()); - row.setUpdatedAt(System.currentTimeMillis()); + row.setUpdatedAt(Instant.now()); row.setData(data); photos.insert(row); } else { row.setContentType(photo.contentType()); - row.setUpdatedAt(System.currentTimeMillis()); + row.setUpdatedAt(Instant.now()); row.setData(data); } profile.setHasPhoto(true); @@ -268,7 +269,7 @@ private ContactDto view(String viewer, Profile profile, List peers) boolean reciprocal = mine == null || !NOBODY.equals(mine.getLastSeen()); if (reciprocal && allowed(viewer, profile, theirs == null ? EVERYONE : theirs.getLastSeen(), peers)) { - lastSeen = live.online(username) ? -1L : profile.getLastSeenAt(); + lastSeen = live.online(username) ? -1L : profile.getLastSeenAt().toEpochMilli(); } boolean photo = profile.isHasPhoto() && allowed(viewer, profile, photoSetting(username), peers); diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/device/Devices.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/device/Devices.java index a8dfbc75a8d..6862616a0c3 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/device/Devices.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/device/Devices.java @@ -41,6 +41,7 @@ import com.codenameone.examples.parley.repository.ProfileRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -109,8 +110,8 @@ public DeviceDto register(String username, DeviceRegistrationDto request) throws row.setSignedPreKeyId(signed.id()); row.setSignedPreKey(signed.publicKey()); row.setSignedPreKeySignature(signed.signature()); - row.setCreatedAt(now); - row.setLastSeenAt(now); + row.setCreatedAt(Instant.ofEpochMilli(now)); + row.setLastSeenAt(Instant.ofEpochMilli(now)); devices.insert(row); store(row.getId(), request.oneTimePreKeys()); return toDto(row); @@ -197,8 +198,8 @@ public boolean owns(String username, String device) { @Transactional public void seen(String username, String device) { long now = System.currentTimeMillis(); - devices.seen(device, now); - profiles.seen(username, now); + devices.seen(device, Instant.ofEpochMilli(now)); + profiles.seen(username, Instant.ofEpochMilli(now)); } /// The device, or a 404 when it is not the caller's: a device of somebody @@ -296,7 +297,7 @@ static String key(String value, String what) { } private static DeviceDto toDto(Device row) { - return new DeviceDto(row.getId(), row.getName(), row.getPlatform(), row.getCreatedAt(), - row.getLastSeenAt()); + return new DeviceDto(row.getId(), row.getName(), row.getPlatform(), row.getCreatedAt().toEpochMilli(), + row.getLastSeenAt().toEpochMilli()); } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/BridgeEvent.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/BridgeEvent.java index af3e1c5e5d4..8fdc22847f1 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/BridgeEvent.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/BridgeEvent.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A webhook event already posted, keyed by the network and its own id for /// the event. Telegram and WhatsApp retry a delivery whose answer they did @@ -32,12 +33,12 @@ public class BridgeEvent { private String id = ""; @Column(nullable = false) - private long receivedAt; + private Instant receivedAt = Instant.EPOCH; public BridgeEvent() { } - public BridgeEvent(String id, long receivedAt) { + public BridgeEvent(String id, Instant receivedAt) { this.id = id; this.receivedAt = receivedAt; } @@ -50,11 +51,11 @@ public void setId(String id) { this.id = id; } - public long getReceivedAt() { + public Instant getReceivedAt() { return receivedAt; } - public void setReceivedAt(long receivedAt) { + public void setReceivedAt(Instant receivedAt) { this.receivedAt = receivedAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/BridgeLink.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/BridgeLink.java index 766ad68ecb6..79737385bf6 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/BridgeLink.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/BridgeLink.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A Parley conversation linked to a chat on Telegram or WhatsApp. @Entity @@ -45,7 +46,7 @@ public class BridgeLink { private String createdBy = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public BridgeLink() { } @@ -98,11 +99,11 @@ public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/CallRecord.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/CallRecord.java index a46ab855659..2a86dfb3be8 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/CallRecord.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/CallRecord.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A voice or video call, from ringing to hang-up. @Entity @@ -51,13 +52,13 @@ public class CallRecord { private String state = ""; @Column(nullable = false) - private long startedAt; + private Instant startedAt = Instant.EPOCH; @Column(nullable = false) - private long answeredAt; + private Instant answeredAt = Instant.EPOCH; @Column(nullable = false) - private long endedAt; + private Instant endedAt = Instant.EPOCH; public CallRecord() { } @@ -126,27 +127,27 @@ public void setState(String state) { this.state = state; } - public long getStartedAt() { + public Instant getStartedAt() { return startedAt; } - public void setStartedAt(long startedAt) { + public void setStartedAt(Instant startedAt) { this.startedAt = startedAt; } - public long getAnsweredAt() { + public Instant getAnsweredAt() { return answeredAt; } - public void setAnsweredAt(long answeredAt) { + public void setAnsweredAt(Instant answeredAt) { this.answeredAt = answeredAt; } - public long getEndedAt() { + public Instant getEndedAt() { return endedAt; } - public void setEndedAt(long endedAt) { + public void setEndedAt(Instant endedAt) { this.endedAt = endedAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ClosedAccount.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ClosedAccount.java index 218bcca199d..fe2a48f48da 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ClosedAccount.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ClosedAccount.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// What is left of an account that was closed: the hash of its e-mail, kept so /// that the address cannot be registered again. @@ -31,7 +32,7 @@ public class ClosedAccount { private String usernameHash = ""; @Column(nullable = false) - private long closedAt; + private Instant closedAt = Instant.EPOCH; public ClosedAccount() { } @@ -44,11 +45,11 @@ public void setUsernameHash(String usernameHash) { this.usernameHash = usernameHash; } - public long getClosedAt() { + public Instant getClosedAt() { return closedAt; } - public void setClosedAt(long closedAt) { + public void setClosedAt(Instant closedAt) { this.closedAt = closedAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ContactBlock.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ContactBlock.java index d724142d9cd..7530dcda457 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ContactBlock.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ContactBlock.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One account blocking another. @Entity @@ -36,7 +37,7 @@ public class ContactBlock { private String blocked = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public ContactBlock() { } @@ -65,11 +66,11 @@ public void setBlocked(String blocked) { this.blocked = blocked; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Conversation.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Conversation.java index fe392c733ed..c3b0492f6e3 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Conversation.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Conversation.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A direct chat, a group or a channel. @Entity @@ -51,10 +52,10 @@ public class Conversation { private String createdBy = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) - private long lastActivityAt; + private Instant lastActivityAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(400)") private String directKey = ""; @@ -126,19 +127,19 @@ public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public long getLastActivityAt() { + public Instant getLastActivityAt() { return lastActivityAt; } - public void setLastActivityAt(long lastActivityAt) { + public void setLastActivityAt(Instant lastActivityAt) { this.lastActivityAt = lastActivityAt; } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ConversationPhoto.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ConversationPhoto.java index 42fd1c7283b..585299d0207 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ConversationPhoto.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ConversationPhoto.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A group's photo. @Entity @@ -33,7 +34,7 @@ public class ConversationPhoto { private String contentType = ""; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; @Column(nullable = false) private byte[] data = new byte[0]; @@ -57,11 +58,11 @@ public void setContentType(String contentType) { this.contentType = contentType; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Device.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Device.java index b5ef39ad02b..da2a9fa2240 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Device.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Device.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One device of an account, with the public keys it published. Private keys /// never leave the device; the server hands these out so others can open @@ -53,10 +54,10 @@ public class Device { private String signedPreKeySignature = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) - private long lastSeenAt; + private Instant lastSeenAt = Instant.EPOCH; public Device() { } @@ -125,19 +126,19 @@ public void setSignedPreKeySignature(String signedPreKeySignature) { this.signedPreKeySignature = signedPreKeySignature; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public long getLastSeenAt() { + public Instant getLastSeenAt() { return lastSeenAt; } - public void setLastSeenAt(long lastSeenAt) { + public void setLastSeenAt(Instant lastSeenAt) { this.lastSeenAt = lastSeenAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Envelope.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Envelope.java index f0ff74365fc..a7c11c43ae5 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Envelope.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Envelope.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One encrypted copy of a message, waiting for one device to fetch it. It is /// deleted when the device acknowledges it, or when its disappearing timer runs @@ -59,10 +60,10 @@ public class Envelope { private byte[] payload = new byte[0]; @Column(nullable = false) - private long sentAt; + private Instant sentAt = Instant.EPOCH; @Column(nullable = false) - private long expiresAt; + private Instant expiresAt = Instant.EPOCH; public Envelope() { } @@ -147,19 +148,19 @@ public void setPayload(byte[] payload) { this.payload = payload; } - public long getSentAt() { + public Instant getSentAt() { return sentAt; } - public void setSentAt(long sentAt) { + public void setSentAt(Instant sentAt) { this.sentAt = sentAt; } - public long getExpiresAt() { + public Instant getExpiresAt() { return expiresAt; } - public void setExpiresAt(long expiresAt) { + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/InviteLink.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/InviteLink.java index de7fa5c6e95..77f49fb3036 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/InviteLink.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/InviteLink.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A code that lets whoever holds it join a group. @Entity @@ -36,10 +37,10 @@ public class InviteLink { private String createdBy = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) - private long expiresAt; + private Instant expiresAt = Instant.EPOCH; public InviteLink() { } @@ -68,19 +69,19 @@ public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public long getExpiresAt() { + public Instant getExpiresAt() { return expiresAt; } - public void setExpiresAt(long expiresAt) { + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/LiveTicket.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/LiveTicket.java index 4d4f5ce392f..bcc13b8b614 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/LiveTicket.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/LiveTicket.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A ticket for one connection to the live channel, as its hash. @Entity @@ -33,7 +34,7 @@ public class LiveTicket { private String username = ""; @Column(nullable = false) - private long expiresAt; + private Instant expiresAt = Instant.EPOCH; public LiveTicket() { } @@ -54,11 +55,11 @@ public void setUsername(String username) { this.username = username; } - public long getExpiresAt() { + public Instant getExpiresAt() { return expiresAt; } - public void setExpiresAt(long expiresAt) { + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/MediaBlob.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/MediaBlob.java index 78c7fa4154c..a025c07fb59 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/MediaBlob.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/MediaBlob.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An encrypted attachment. The key is in the message that refers to it. @Entity @@ -36,7 +37,7 @@ public class MediaBlob { private int size; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) private byte[] data = new byte[0]; @@ -68,11 +69,11 @@ public void setSize(int size) { this.size = size; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Membership.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Membership.java index f4b5e9aab52..a9178067f42 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Membership.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Membership.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One account's place in a conversation, and its own view of it. @Entity @@ -48,7 +49,7 @@ public class Membership { private boolean pinned; @Column(nullable = false) - private long joinedAt; + private Instant joinedAt = Instant.EPOCH; public Membership() { } @@ -109,11 +110,11 @@ public void setPinned(boolean pinned) { this.pinned = pinned; } - public long getJoinedAt() { + public Instant getJoinedAt() { return joinedAt; } - public void setJoinedAt(long joinedAt) { + public void setJoinedAt(Instant joinedAt) { this.joinedAt = joinedAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/MessageLog.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/MessageLog.java index beee8559cde..4e2d8b39705 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/MessageLog.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/MessageLog.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// That a message was sent: who, where and when, never what. It makes a /// retried send idempotent and feeds the admin's counts. @@ -43,7 +44,7 @@ public class MessageLog { private String kind = ""; @Column(nullable = false) - private long sentAt; + private Instant sentAt = Instant.EPOCH; public MessageLog() { } @@ -88,11 +89,11 @@ public void setKind(String kind) { this.kind = kind; } - public long getSentAt() { + public Instant getSentAt() { return sentAt; } - public void setSentAt(long sentAt) { + public void setSentAt(Instant sentAt) { this.sentAt = sentAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ModerationEvent.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ModerationEvent.java index 49fe0e5d86f..17ad2945e5b 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ModerationEvent.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ModerationEvent.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One thing an admin did to an account, and why. Written once, never changed. @Entity @@ -33,7 +34,7 @@ public class ModerationEvent { private String username = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(190)") private String actor = ""; @@ -63,11 +64,11 @@ public void setUsername(String username) { this.username = username; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/PhoneCode.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/PhoneCode.java index 4084d725165..b401b05eb4e 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/PhoneCode.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/PhoneCode.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// The verification code an account was last sent, as its hash. @Entity @@ -33,20 +34,20 @@ public class PhoneCode { private String codeHash = ""; @Column(nullable = false) - private long expiresAt; + private Instant expiresAt = Instant.EPOCH; @Column(nullable = false) private int attempts; @Column(nullable = false) - private long sentAt; + private Instant sentAt = Instant.EPOCH; /// The code sent before this one, while it is still good, or empty. @Column(nullable = false, type = "VARCHAR(64)") private String previousHash = ""; @Column(nullable = false) - private long previousExpiresAt; + private Instant previousExpiresAt = Instant.EPOCH; /// The guesses already taken at the code before, which keeps the budget /// it had rather than starting a new one when another code is sent. @@ -72,11 +73,11 @@ public void setCodeHash(String codeHash) { this.codeHash = codeHash; } - public long getExpiresAt() { + public Instant getExpiresAt() { return expiresAt; } - public void setExpiresAt(long expiresAt) { + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } @@ -88,11 +89,11 @@ public void setAttempts(int attempts) { this.attempts = attempts; } - public long getSentAt() { + public Instant getSentAt() { return sentAt; } - public void setSentAt(long sentAt) { + public void setSentAt(Instant sentAt) { this.sentAt = sentAt; } @@ -104,11 +105,11 @@ public void setPreviousHash(String previousHash) { this.previousHash = previousHash; } - public long getPreviousExpiresAt() { + public Instant getPreviousExpiresAt() { return previousExpiresAt; } - public void setPreviousExpiresAt(long previousExpiresAt) { + public void setPreviousExpiresAt(Instant previousExpiresAt) { this.previousExpiresAt = previousExpiresAt; } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Profile.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Profile.java index d0412fa68c5..40dcc9b1bb5 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Profile.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Profile.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An account's profile: who it is to the people it talks to. /// @@ -48,10 +49,10 @@ public class Profile { private boolean hasPhoto; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) - private long lastSeenAt; + private Instant lastSeenAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(8)") private String language = ""; @@ -113,19 +114,19 @@ public void setHasPhoto(boolean hasPhoto) { this.hasPhoto = hasPhoto; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public long getLastSeenAt() { + public Instant getLastSeenAt() { return lastSeenAt; } - public void setLastSeenAt(long lastSeenAt) { + public void setLastSeenAt(Instant lastSeenAt) { this.lastSeenAt = lastSeenAt; } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ProfilePhoto.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ProfilePhoto.java index 7853aaba4f5..50289ca95c2 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ProfilePhoto.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/ProfilePhoto.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An account's profile photo. @Entity @@ -33,7 +34,7 @@ public class ProfilePhoto { private String contentType = ""; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; @Column(nullable = false) private byte[] data = new byte[0]; @@ -57,11 +58,11 @@ public void setContentType(String contentType) { this.contentType = contentType; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/PushDevice.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/PushDevice.java index 8c5377843d2..7e2d1dbf673 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/PushDevice.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/PushDevice.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A device an account is sent push notifications on. /// @@ -46,7 +47,7 @@ public class PushDevice { private String platform = ""; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; public PushDevice() { } @@ -91,11 +92,11 @@ public void setPlatform(String platform) { this.platform = platform; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Report.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Report.java index 784c72f5341..2d4cc27c840 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Report.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/domain/Report.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An abuse report, and what the admins did about it. @Entity @@ -45,7 +46,7 @@ public class Report { private String evidence = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(16)") private String status = ""; @@ -107,11 +108,11 @@ public void setEvidence(String evidence) { this.evidence = evidence; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/live/LiveTickets.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/live/LiveTickets.java index 685412bed0f..1fda517193f 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/live/LiveTickets.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/live/LiveTickets.java @@ -28,6 +28,7 @@ import com.codenameone.examples.parley.repository.LiveTicketRepository; import java.io.IOException; +import java.time.Instant; /// Tickets for the live channel. /// @@ -58,7 +59,7 @@ public TicketDto issue(String username) throws IOException { LiveTicket row = new LiveTicket(); row.setTicketHash(Ids.sha256(ticket)); row.setUsername(username); - row.setExpiresAt(System.currentTimeMillis() + TICKET_SECONDS * 1000L); + row.setExpiresAt(Instant.now().plusSeconds(TICKET_SECONDS)); tickets.insert(row); return new TicketDto(ticket, TICKET_SECONDS); } @@ -78,7 +79,7 @@ public String redeem(String ticket) throws IOException { return null; } String username = row.getUsername(); - long expiresAt = row.getExpiresAt(); + long expiresAt = row.getExpiresAt().toEpochMilli(); // One delete statement: the count it answers is what says this // connection, and not another presenting the same ticket, used it. int removed = tickets.deleteByTicketHash(hash); @@ -92,7 +93,7 @@ public String redeem(String ticket) throws IOException { @Scheduled(fixedDelay = 60000, initialDelay = 60000) @Transactional public void sweep() throws IOException { - tickets.deleteByExpiresAtLessThan(System.currentTimeMillis()); + tickets.deleteByExpiresAtLessThan(Instant.now()); } /// Forgets the tickets of an account that is being closed. diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/push/PushDevices.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/push/PushDevices.java index 7cb6d50afc1..84aea8499e5 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/push/PushDevices.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/push/PushDevices.java @@ -30,6 +30,7 @@ import com.codenameone.examples.parley.repository.PushDeviceRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -115,7 +116,7 @@ private void makeRoom(String username) { while (held.size() >= MAX_PER_ACCOUNT) { PushDevice oldest = held.get(0); for (PushDevice each : held) { - if (each.getUpdatedAt() < oldest.getUpdatedAt()) { + if (each.getUpdatedAt().isBefore(oldest.getUpdatedAt())) { oldest = each; } } @@ -168,7 +169,7 @@ private List targetsOf(String username, boolean voip) { private static void fill(PushDevice row, String username, PushDeviceDto device, long now) { row.setUsername(username); row.setPlatform(Text.optional(device.platform(), 32, "the platform")); - row.setUpdatedAt(now); + row.setUpdatedAt(Instant.ofEpochMilli(now)); } /// The device as a target of the push service, which also spells its diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/BridgeEventRepository.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/BridgeEventRepository.java index 3188205f617..47cd4578f6f 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/BridgeEventRepository.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/BridgeEventRepository.java @@ -21,9 +21,10 @@ import com.codename1.orm.repository.CrudRepository; import com.codename1.orm.repository.Repository; import com.codenameone.examples.parley.domain.BridgeEvent; +import java.time.Instant; /// Webhook events already posted. @Repository(entity = BridgeEvent.class, key = String.class) public interface BridgeEventRepository extends CrudRepository { - int deleteByReceivedAtLessThan(long before); + int deleteByReceivedAtLessThan(Instant before); } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/CallRecordRepository.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/CallRecordRepository.java index f993ecd4e05..c7eafc30338 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/CallRecordRepository.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/CallRecordRepository.java @@ -25,6 +25,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.parley.domain.CallRecord; +import java.time.Instant; import java.util.List; /// Calls, live and past. @@ -42,16 +43,16 @@ public interface CallRecordRepository extends CrudRepository @Query("select c from CallRecord c where c.caller = :username or c.callee = :username order by c.startedAt desc") List historyOf(@Param("username") String username); - @Query("select c from CallRecord c where (c.caller = :username or c.callee = :username) and c.endedAt = 0") - List liveOf(@Param("username") String username); + @Query("select c from CallRecord c where (c.caller = :username or c.callee = :username) and c.endedAt = :none") + List liveOf(@Param("username") String username, @Param("none") Instant none); - @Query("select c from CallRecord c where c.endedAt = 0 and c.startedAt < :before") - List openSince(@Param("before") long before); + @Query("select c from CallRecord c where c.endedAt = :none and c.startedAt < :before") + List openSince(@Param("before") Instant before, @Param("none") Instant none); - long countByStartedAtGreaterThanEqual(long since); + long countByStartedAtGreaterThanEqual(Instant since); @Query("select c.startedAt from CallRecord c where c.startedAt >= :since") - List startedSince(@Param("since") long since); + List startedSince(@Param("since") Instant since); @Modifying @Query("delete from CallRecord c where c.caller = :username or c.callee = :username") diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ConversationRepository.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ConversationRepository.java index 81ed407f776..b91dcea7e89 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ConversationRepository.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ConversationRepository.java @@ -25,6 +25,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.parley.domain.Conversation; +import java.time.Instant; import java.util.List; /// Conversations of every kind. @@ -48,5 +49,5 @@ public interface ConversationRepository extends CrudRepository { @Modifying @Query("update Device d set d.lastSeenAt = :at where d.id = :id") - int seen(@Param("id") String id, @Param("at") long at); + int seen(@Param("id") String id, @Param("at") Instant at); } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/EnvelopeRepository.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/EnvelopeRepository.java index e48afdf5652..8b9e7b16e14 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/EnvelopeRepository.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/EnvelopeRepository.java @@ -25,6 +25,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.parley.domain.Envelope; +import java.time.Instant; import java.util.List; /// Envelopes waiting for their device. @@ -45,9 +46,9 @@ public interface EnvelopeRepository extends CrudRepository { /// Removes what the disappearing timer has run out on. @Modifying - @Query("delete from Envelope e where e.expiresAt > 0 and e.expiresAt <= :now") - int expire(@Param("now") long now); + @Query("delete from Envelope e where e.expiresAt > :none and e.expiresAt <= :now") + int expire(@Param("now") Instant now, @Param("none") Instant none); /// Removes what nobody fetched for a month: the device is gone or lost. - int deleteBySentAtLessThan(long before); + int deleteBySentAtLessThan(Instant before); } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/LiveTicketRepository.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/LiveTicketRepository.java index f8f8857177b..4bb95fd8253 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/LiveTicketRepository.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/LiveTicketRepository.java @@ -21,6 +21,7 @@ import com.codename1.orm.repository.CrudRepository; import com.codename1.orm.repository.Repository; import com.codenameone.examples.parley.domain.LiveTicket; +import java.time.Instant; /// The tickets that open a live connection. Only the hash of a ticket is /// stored, and it is the row's key. @@ -33,7 +34,7 @@ public interface LiveTicketRepository extends CrudRepository int deleteByTicketHash(String ticketHash); /// Deletes the tickets that went stale before `now`. - int deleteByExpiresAtLessThan(long now); + int deleteByExpiresAtLessThan(Instant now); int deleteByUsername(String username); } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/MediaBlobRepository.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/MediaBlobRepository.java index db2dc77aca2..76e0471caf0 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/MediaBlobRepository.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/MediaBlobRepository.java @@ -23,14 +23,15 @@ import com.codename1.orm.repository.Query; import com.codename1.orm.repository.Repository; import com.codenameone.examples.parley.domain.MediaBlob; +import java.time.Instant; /// Encrypted attachments. @Repository(entity = MediaBlob.class, key = String.class) public interface MediaBlobRepository extends CrudRepository { int deleteByOwner(String owner); - int deleteByCreatedAtLessThan(long before); + int deleteByCreatedAtLessThan(Instant before); @Query("select coalesce(sum(m.size), 0) from MediaBlob m where m.owner = :owner and m.createdAt >= :since") - Long storedSince(@Param("owner") String owner, @Param("since") long since); + Long storedSince(@Param("owner") String owner, @Param("since") Instant since); } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/MessageLogRepository.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/MessageLogRepository.java index 4667c1949ba..f0d87a050e2 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/MessageLogRepository.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/MessageLogRepository.java @@ -24,19 +24,20 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.parley.domain.MessageLog; +import java.time.Instant; import java.util.List; /// That messages were sent, never what they said. @Repository(entity = MessageLog.class, key = String.class) public interface MessageLogRepository extends CrudRepository { - long countBySentAtGreaterThanEqual(long since); + long countBySentAtGreaterThanEqual(Instant since); long countBySender(String sender); @Query("select m.sentAt, m.sender from MessageLog m where m.sentAt >= :since and m.kind = 'MESSAGE'") - List since(@Param("since") long since); + List since(@Param("since") Instant since); int deleteBySender(String sender); - int deleteBySentAtLessThan(long before); + int deleteBySentAtLessThan(Instant before); } diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ModerationEventRepository.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ModerationEventRepository.java index ee2385462bd..38ecf943b74 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ModerationEventRepository.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ModerationEventRepository.java @@ -24,6 +24,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.parley.domain.ModerationEvent; +import java.time.Instant; import java.util.List; /// The record of what the admins did to each account. @@ -32,7 +33,7 @@ public interface ModerationEventRepository extends CrudRepository findTop100ByUsernameOrderByCreatedAtDescIdAsc(String username); diff --git a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ProfileRepository.java b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ProfileRepository.java index cfbaa34aee4..a94031b9ca2 100644 --- a/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ProfileRepository.java +++ b/scripts/parley/backend/src/main/java/com/codenameone/examples/parley/repository/ProfileRepository.java @@ -25,6 +25,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.parley.domain.Profile; +import java.time.Instant; import java.util.List; /// Profiles, keyed by the e-mail an account signs in with. @@ -61,9 +62,9 @@ public interface ProfileRepository extends CrudRepository { /// When each account made since `since` was made. @Query("select p.createdAt from Profile p where p.createdAt >= :since") - List signUps(@Param("since") long since); + List signUps(@Param("since") Instant since); @Modifying @Query("update Profile p set p.lastSeenAt = :at where p.username = :username") - int seen(@Param("username") String username, @Param("at") long at); + int seen(@Param("username") String username, @Param("at") Instant at); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/Rows.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/Rows.java index 6c84eae362d..40bef0bb2e1 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/Rows.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/Rows.java @@ -21,6 +21,7 @@ import com.codenameone.examples.savor.api.DeliveryState; import com.codenameone.examples.savor.api.OrderState; +import java.time.Instant; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -41,6 +42,13 @@ public static long number(Object value) { return value instanceof Number ? ((Number) value).longValue() : 0L; } + /// A column holding a point in time as milliseconds since the epoch: the + /// `Instant` an entity's time field is read as, or 0 for null or anything + /// else. + public static long millis(Object value) { + return value instanceof Instant ? ((Instant) value).toEpochMilli() : 0L; + } + /// A column as text; empty for null. public static String text(Object value) { return value == null ? "" : String.valueOf(value); diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/AccountCleanup.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/AccountCleanup.java index ecac220794f..aa2f296d130 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/AccountCleanup.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/AccountCleanup.java @@ -39,6 +39,7 @@ import com.codenameone.examples.savor.repository.DeliveryActivityRepository; import com.codenameone.examples.savor.repository.DeliveryRepository; +import java.time.Instant; import java.util.List; /// What closing or restricting an account does to the rows other parts of the @@ -205,7 +206,7 @@ public void removeEverythingOf(String username) { && staff.findByRestaurantId(restaurantId).size() < 2) { restaurant.setStatus(Catalog.SUSPENDED); restaurant.setReason("Its only merchant closed their account"); - restaurant.setUpdatedAt(System.currentTimeMillis()); + restaurant.setUpdatedAt(Instant.now()); } } staff.deleteByUsername(username); diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/Accounts.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/Accounts.java index d761c97ad69..8994ab9d3f9 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/Accounts.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/Accounts.java @@ -43,6 +43,7 @@ import com.codenameone.examples.savor.repository.ProfileRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -184,7 +185,7 @@ void create(String username, String password, String displayName, String phone, profile.setPhoneVerified(phoneVerified); profile.setVehicle(vehicle); profile.setPlate(plate); - profile.setCreatedAt(openedAt); + profile.setCreatedAt(Instant.ofEpochMilli(openedAt)); profiles.insert(profile); if (courier) { applications.grant(username, username); @@ -517,7 +518,7 @@ private void retire(String username) throws IOException { if (!closed.existsById(hash)) { ClosedAccount row = new ClosedAccount(); row.setUsernameHash(hash); - row.setClosedAt(System.currentTimeMillis()); + row.setClosedAt(Instant.now()); closed.insert(row); } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/DemoAccounts.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/DemoAccounts.java index 24fc43cac8e..d3a0fffd763 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/DemoAccounts.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/DemoAccounts.java @@ -40,6 +40,7 @@ import com.codenameone.examples.savor.order.DemoOrders; import java.io.IOException; +import java.time.Instant; /// The accounts a server starts with. /// @@ -170,7 +171,7 @@ void flag(String username, String why, int daysAgo) throws IOException { profile.setFlagged(true); profile.setFlagReason(why); moderation.record(username, ADMIN, Moderation.FLAG, why, - System.currentTimeMillis() - daysAgo * Days.MILLIS); + Instant.now().minusMillis(daysAgo * Days.MILLIS)); } /// An admin, or the plainest kind of account. @@ -240,7 +241,7 @@ void approved(String username, String name, String colour, String make, String m form.setVehicleYear(year() - 3); form.setVehicleColor(colour); form.setVehiclePlate(plate); - form.setSubmittedAt(handedIn); + form.setSubmittedAt(Instant.ofEpochMilli(handedIn)); form.setReviewedBy(ADMIN); for (int iter = 0; iter < Applications.KINDS.length; iter++) { CourierDocument picture = new CourierDocument(); @@ -248,7 +249,7 @@ void approved(String username, String name, String colour, String make, String m picture.setKind(Applications.KINDS[iter]); picture.setContentType("image/png"); picture.setStatus("accepted"); - picture.setUploadedAt(handedIn); + picture.setUploadedAt(Instant.ofEpochMilli(handedIn)); picture.setData(PLACEHOLDER_PICTURE); documents.insert(picture); } @@ -284,7 +285,7 @@ private void applicant() throws IOException { @Transactional(rollbackFor = IOException.class) void handedIn(String username, int daysAgo) throws IOException { CourierApplication form = forms.findById(username); - form.setSubmittedAt(System.currentTimeMillis() - daysAgo * Days.MILLIS); + form.setSubmittedAt(Instant.ofEpochMilli(System.currentTimeMillis() - daysAgo * Days.MILLIS)); } /// When an account opened that many days ago was opened, so that the chart diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/Moderation.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/Moderation.java index 24ab4f8f2dc..85db0b83e34 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/Moderation.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/Moderation.java @@ -26,6 +26,7 @@ import com.codenameone.examples.savor.repository.ModerationEventRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -60,15 +61,16 @@ public void record(String username, String by, String action, String reason) // came with it -- would otherwise be listed in either order. The later // one is stamped after the one before it, so the list is the order in // which things were done. - Long newest = events.newest(username); - long after = newest == null ? 0L : newest.longValue() + 1L; - record(username, by, action, reason, Math.max(System.currentTimeMillis(), after)); + Instant newest = events.newest(username); + Instant now = Instant.now(); + Instant after = newest == null ? Instant.EPOCH : newest.plusMillis(1L); + record(username, by, action, reason, after.isAfter(now) ? after : now); } /// As [#record(String, String, String, String)], at a time of the caller's /// choosing; the demo data is the one caller that has a past to write. @Transactional - public void record(String username, String by, String action, String reason, long at) + public void record(String username, String by, String action, String reason, Instant at) throws IOException { String why = reason == null ? "" : reason.trim(); ModerationEvent event = new ModerationEvent(); @@ -88,7 +90,7 @@ public List events(String username) throws IOException { List out = new ArrayList(); for (int iter = 0; iter < rows.size(); iter++) { ModerationEvent row = rows.get(iter); - out.add(new ModerationEventDto(row.getCreatedAt(), row.getActor(), row.getAction(), + out.add(new ModerationEventDto(row.getCreatedAt().toEpochMilli(), row.getActor(), row.getAction(), row.getReason())); } return out; diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/PhoneVerification.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/PhoneVerification.java index cb85edf4f8e..92f869eb193 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/PhoneVerification.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/account/PhoneVerification.java @@ -31,6 +31,7 @@ import com.codenameone.examples.savor.sms.SmsSender; import java.io.IOException; +import java.time.Instant; /// Proves an account's phone number by texting it a code. /// @@ -104,14 +105,14 @@ void store(String username, String codeHash, long now) throws IOException { // wait. Otherwise both pass the check below and both send a text. accounts.hold(username); PhoneCode pending = codes.findById(username); - if (pending != null && now - pending.getSentAt() < RESEND_SECONDS * 1000L) { + if (pending != null && now - pending.getSentAt().toEpochMilli() < RESEND_SECONDS * 1000L) { throw new ResponseStatusException(429, "Wait a moment before asking for another code"); } boolean first = pending == null; if (first) { pending = new PhoneCode(); pending.setUsername(username); - } else if (pending.getExpiresAt() >= now && pending.getAttempts() < MAX_ATTEMPTS) { + } else if (pending.getExpiresAt().toEpochMilli() >= now && pending.getAttempts() < MAX_ATTEMPTS) { // With the guesses it has used: asking for another code must not // buy the old one a fresh set. pending.setPreviousHash(pending.getCodeHash()); @@ -119,13 +120,13 @@ void store(String username, String codeHash, long now) throws IOException { pending.setPreviousAttempts(pending.getAttempts()); } else { pending.setPreviousHash(""); - pending.setPreviousExpiresAt(0L); + pending.setPreviousExpiresAt(Instant.EPOCH); pending.setPreviousAttempts(0); } pending.setCodeHash(codeHash); - pending.setExpiresAt(now + CODE_SECONDS * 1000L); + pending.setExpiresAt(Instant.ofEpochMilli(now + CODE_SECONDS * 1000L)); pending.setAttempts(0); - pending.setSentAt(now); + pending.setSentAt(Instant.ofEpochMilli(now)); if (first) { codes.insert(pending); } @@ -148,7 +149,7 @@ void discard(String username, String codeHash) throws IOException { return; } if (pending.getPreviousHash().length() == 0 - || pending.getPreviousExpiresAt() < System.currentTimeMillis()) { + || pending.getPreviousExpiresAt().isBefore(Instant.now())) { codes.deleteById(username); return; } @@ -156,9 +157,9 @@ void discard(String username, String codeHash) throws IOException { pending.setExpiresAt(pending.getPreviousExpiresAt()); pending.setAttempts(pending.getPreviousAttempts()); pending.setPreviousHash(""); - pending.setPreviousExpiresAt(0L); + pending.setPreviousExpiresAt(Instant.EPOCH); pending.setPreviousAttempts(0); - pending.setSentAt(0L); + pending.setSentAt(Instant.EPOCH); } /// Checks the code the user typed. Answers 400 for a wrong or expired one @@ -186,7 +187,7 @@ boolean guess(String username, String code) throws IOException { // row the other has. accounts.hold(username); PhoneCode pending = codes.findById(username); - if (pending == null || pending.getExpiresAt() < System.currentTimeMillis()) { + if (pending == null || pending.getExpiresAt().isBefore(Instant.now())) { throw new ResponseStatusException(400, "That code has expired. Ask for a new one"); } if (pending.getAttempts() >= MAX_ATTEMPTS) { @@ -222,7 +223,7 @@ boolean guess(String username, String code) throws IOException { boolean previous = Crypto.equalsConstantTime(given, pending.getPreviousHash().getBytes("UTF-8")) && pending.getPreviousHash().length() > 0 - && pending.getPreviousExpiresAt() >= System.currentTimeMillis() + && !pending.getPreviousExpiresAt().isBefore(Instant.now()) && counted != null && counted.getPreviousAttempts() <= MAX_ATTEMPTS; if (!current && !previous) { return false; diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/admin/Statistics.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/admin/Statistics.java index 5e476f363bf..124da6a1ff0 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/admin/Statistics.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/admin/Statistics.java @@ -48,6 +48,7 @@ import com.codenameone.examples.savor.delivery.Matcher; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -123,8 +124,8 @@ public AdminStatsDto dashboard() throws IOException { } } int online = (int) cars.countByOnlineTrueAndLastSeenGreaterThanEqual( - now - Matcher.FRESH_MILLIS); - int today = (int) orders.countByPlacedAtGreaterThanEqual(Days.start(now)); + Instant.ofEpochMilli(now - Matcher.FRESH_MILLIS)); + int today = (int) orders.countByPlacedAtGreaterThanEqual(Instant.ofEpochMilli(Days.start(now))); int active = (int) orders.countByStateIn(ACTIVE); int done = (int) orders.countByStateIn(new OrderState[] {OrderState.DELIVERED}); long revenue = Rows.number(orders.totals(OrderState.DELIVERED, PAID)); @@ -153,10 +154,10 @@ public StatsSeriesDto series(int days) throws IOException { long finished = 0L; long totalSum = 0L; long tookMillis = 0L; - List timeline = orders.timeline(since); + List timeline = orders.timeline(Instant.ofEpochMilli(since)); for (int iter = 0; iter < timeline.size(); iter++) { Object[] order = timeline.get(iter); - long at = whole(order[1]); + long at = Rows.millis(order[1]); OrderState state = Rows.orderState(order[2]); byHour[(int) (at % Days.MILLIS / 3600000L)]++; if (state != null) { @@ -168,7 +169,7 @@ public StatsSeriesDto series(int days) throws IOException { delivered++; finished++; totalSum += whole(order[3]); - tookMillis += Math.max(0L, whole(order[5]) - at); + tookMillis += Math.max(0L, Rows.millis(order[5]) - at); } else if (ended(state)) { finished++; } @@ -186,7 +187,7 @@ public StatsSeriesDto series(int days) throws IOException { } } Map completedBy = new HashMap(); - List perCourier = deliveries.countByCourier(since, DeliveryState.COMPLETED); + List perCourier = deliveries.countByCourier(Instant.ofEpochMilli(since), DeliveryState.COMPLETED); for (int iter = 0; iter < perCourier.size(); iter++) { completedBy.put(Rows.text(perCourier.get(iter)[0]), new int[] {(int) whole(perCourier.get(iter)[1])}); @@ -203,7 +204,7 @@ public StatsSeriesDto series(int days) throws IOException { } } List byRestaurant = new ArrayList(); - List kitchens = orders.countByRestaurant(since); + List kitchens = orders.countByRestaurant(Instant.ofEpochMilli(since)); for (int iter = 0; iter < kitchens.size(); iter++) { // Counted by id, and named as the restaurant is called now: two // kitchens may share a name, and one may have been renamed. @@ -220,9 +221,9 @@ public StatsSeriesDto series(int days) throws IOException { double completionRate = finished == 0L ? 0d : Math.round(delivered * 100d / finished) / 100d; - List signUps = profiles.signUps(since); + List signUps = profiles.signUps(Instant.ofEpochMilli(since)); for (int iter = 0; iter < signUps.size(); iter++) { - int index = (int) ((signUps.get(iter).longValue() - since) / Days.MILLIS); + int index = (int) ((signUps.get(iter).toEpochMilli() - since) / Days.MILLIS); if (index >= 0 && index < span) { dayNewUsers[index]++; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/Catalog.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/Catalog.java index 0e61b522f0d..0e126aa1b5f 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/Catalog.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/Catalog.java @@ -45,6 +45,7 @@ import com.codenameone.examples.savor.repository.PhotoRepository; import com.codenameone.examples.savor.repository.RestaurantRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -343,7 +344,7 @@ public RestaurantSummaryDto favorite(String viewer, String id, boolean keep) Favorite row = new Favorite(); row.setUsername(viewer); row.setRestaurantId(id); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); favorites.insert(row); } else if (!keep && kept) { favorites.deleteById(key); diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/DemoRestaurants.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/DemoRestaurants.java index 0fadb79eb42..2a23086e5ae 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/DemoRestaurants.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/DemoRestaurants.java @@ -42,6 +42,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.time.Instant; /// The restaurants a development server starts with: a dozen around San /// Francisco's waterfront, one per cuisine on the home screen's row, each with @@ -266,8 +267,8 @@ public void seed(String merchant) throws IOException { restaurant.setPhotoId(photoFor(RESTAURANT_PHOTOS, restaurant.getId(), restaurant.getId())); restaurant.setApplicant(iter == 0 ? merchant : ""); restaurant.setReason(""); - restaurant.setCreatedAt(now - (60 - iter) * 86400000L); - restaurant.setUpdatedAt(now); + restaurant.setCreatedAt(Instant.ofEpochMilli(now - (60 - iter) * 86400000L)); + restaurant.setUpdatedAt(Instant.ofEpochMilli(now)); restaurants.insert(restaurant); menu(restaurant.getId(), MENUS[iter]); } @@ -291,8 +292,8 @@ public void seed(String merchant) throws IOException { waiting.setPhotoId(""); waiting.setApplicant(""); waiting.setReason(""); - waiting.setCreatedAt(now - 2L * 86400000L); - waiting.setUpdatedAt(now - 2L * 86400000L); + waiting.setCreatedAt(Instant.ofEpochMilli(now - 2L * 86400000L)); + waiting.setUpdatedAt(Instant.ofEpochMilli(now - 2L * 86400000L)); restaurants.insert(waiting); promo("WELCOME10", 10, 0L, 1500L, now); @@ -371,7 +372,7 @@ private String photo(String key, String restaurantId) throws IOException { row.setRestaurantId(restaurantId); row.setContentType(type); row.setData(read(file)); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); photos.insert(row); return id; } @@ -395,7 +396,7 @@ private void promo(String code, int percent, long amount, long minimum, long now promo.setAmountOffCents(amount); promo.setMinimumCents(minimum); promo.setActive(true); - promo.setCreatedAt(now); + promo.setCreatedAt(Instant.ofEpochMilli(now)); promos.insert(promo); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/Restaurants.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/Restaurants.java index 869bc359a6d..f90eecb347e 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/Restaurants.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/catalog/Restaurants.java @@ -56,6 +56,7 @@ import com.codenameone.examples.savor.repository.RestaurantStaffRepository; import com.codenameone.examples.savor.Days; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -150,8 +151,8 @@ public RestaurantDto apply(String username, RestaurantEditDto form) throws IOExc restaurant.setReason(""); restaurant.setPhotoId(""); long now = System.currentTimeMillis(); - restaurant.setCreatedAt(now); - restaurant.setUpdatedAt(now); + restaurant.setCreatedAt(Instant.ofEpochMilli(now)); + restaurant.setUpdatedAt(Instant.ofEpochMilli(now)); fill(restaurant, form); restaurants.insert(restaurant); return catalog.detail(restaurant, username, 0d, 0d, true); @@ -182,7 +183,7 @@ public PhotoDto applicationPhoto(String username, PhotoDto photo) throws IOExcep } PhotoDto saved = store(last.getId(), photo); last.setPhotoId(saved.id()); - last.setUpdatedAt(System.currentTimeMillis()); + last.setUpdatedAt(Instant.now()); return saved; } @@ -258,7 +259,7 @@ public RestaurantDto approve(String by, String id) throws IOException { } restaurant.setStatus(Catalog.APPROVED); restaurant.setReason(""); - restaurant.setUpdatedAt(System.currentTimeMillis()); + restaurant.setUpdatedAt(Instant.now()); if (!staff.existsById(Identifier.of(restaurant.getId(), applicant))) { RestaurantStaff row = new RestaurantStaff(); row.setRestaurantId(restaurant.getId()); @@ -281,7 +282,7 @@ public RestaurantDto reject(String by, String id, String reason) throws IOExcept } restaurant.setStatus(Catalog.REJECTED); restaurant.setReason(Text.required(reason, 255, "why it is turned down")); - restaurant.setUpdatedAt(System.currentTimeMillis()); + restaurant.setUpdatedAt(Instant.now()); return catalog.detail(restaurant, null, 0d, 0d, true); } @@ -306,7 +307,7 @@ public RestaurantDto suspend(String by, String id, boolean suspended, String rea } restaurant.setStatus(suspended ? Catalog.SUSPENDED : Catalog.APPROVED); restaurant.setReason(suspended ? Text.required(reason, 255, "why it is suspended") : ""); - restaurant.setUpdatedAt(System.currentTimeMillis()); + restaurant.setUpdatedAt(Instant.now()); return catalog.detail(restaurant, null, 0d, 0d, true); } @@ -350,7 +351,7 @@ public RestaurantDto save(String username, RestaurantEditDto form) throws IOExce ownPhoto(restaurant, form.photoId()); restaurant.setPhotoId(form.photoId()); } - restaurant.setUpdatedAt(System.currentTimeMillis()); + restaurant.setUpdatedAt(Instant.now()); return catalog.detail(restaurant, username, 0d, 0d, true); } @@ -359,7 +360,7 @@ public RestaurantDto save(String username, RestaurantEditDto form) throws IOExce public RestaurantDto pause(String username, boolean paused) throws IOException { Restaurant restaurant = mine(username); restaurant.setPaused(paused); - restaurant.setUpdatedAt(System.currentTimeMillis()); + restaurant.setUpdatedAt(Instant.now()); return catalog.detail(restaurant, username, 0d, 0d, true); } @@ -372,7 +373,7 @@ public MerchantSummaryDto summary(String username) throws IOException { long today = Days.start(now); long week = today - 6L * Days.MILLIS; List delivered = orders.findByRestaurantIdAndStateAndDeliveredAtGreaterThanEqual( - restaurant.getId(), OrderState.DELIVERED, week); + restaurant.getId(), OrderState.DELIVERED, Instant.ofEpochMilli(week)); long count = 0L; long todayCents = 0L; long weekCents = 0L; @@ -386,7 +387,7 @@ public MerchantSummaryDto summary(String username) throws IOException { long earned = order.getSubtotalCents() - order.getDiscountCents() - order.getCommissionCents(); weekCents += earned; - if (order.getDeliveredAt() >= today) { + if (order.getDeliveredAt().toEpochMilli() >= today) { todayCents += earned; count++; } @@ -606,7 +607,7 @@ private PhotoDto store(String restaurantId, PhotoDto photo) throws IOException { row.setRestaurantId(restaurantId); row.setContentType(type); row.setData(bytes); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); photos.insert(row); return new PhotoDto(row.getId(), type, ""); } @@ -624,14 +625,14 @@ private int prune(String restaurantId) { for (int iter = 0; iter < menu.size(); iter++) { used.add(menu.get(iter).getPhotoId()); } - long before = System.currentTimeMillis() - UNUSED_PHOTO_GRACE; + Instant before = Instant.now().minusMillis(UNUSED_PHOTO_GRACE); List stored = photos.stored(restaurantId); int remaining = 0; for (int iter = 0; iter < stored.size(); iter++) { Object id = stored.get(iter)[0]; Object at = stored.get(iter)[1]; - long createdAt = at instanceof Number ? ((Number) at).longValue() : Long.MAX_VALUE; - if (id instanceof String && !used.contains(id) && createdAt < before) { + boolean aged = at instanceof Instant && ((Instant) at).isBefore(before); + if (id instanceof String && !used.contains(id) && aged) { photos.deleteById((String) id); } else { remaining++; diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/courier/Couriers.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/courier/Couriers.java index f1c1253ab0a..484fd01d5fb 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/courier/Couriers.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/courier/Couriers.java @@ -47,6 +47,7 @@ import com.codenameone.examples.savor.delivery.Matcher; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -156,14 +157,14 @@ private Report store(String courier, CourierStatusDto status) throws IOException // is, so the row read here stays managed and its change is written // either way; a statement marked clearAutomatically would detach it, // and a change made after that would be lost. - long since = state != null && state.isOnline() ? now - state.getLastSeen() : 0L; + long since = state != null && state.isOnline() ? now - state.getLastSeen().toEpochMilli() : 0L; boolean first = state == null; if (first) { state = new CourierState(); state.setUsername(courier); } state.setOnline(status.online()); - state.setLastSeen(now); + state.setLastSeen(Instant.ofEpochMilli(now)); // Off line keeps the last position: there is none to report. A first // report stores whatever came with it. if (status.online() || first) { @@ -282,10 +283,10 @@ public EarningsDto earnings(String courier) throws IOException { long now = System.currentTimeMillis(); // The day's trips and the day's money from one query, so the header // that shows them together counts the deliveries that made the sum. - Object[] day = deliveries.paidTotalsSince(courier, now - now % DAY_MILLIS); + Object[] day = deliveries.paidTotalsSince(courier, Instant.ofEpochMilli(now - now % DAY_MILLIS)); int todayCount = day == null ? 0 : (int) Rows.number(day[0]); long today = day == null ? 0L : Rows.number(day[1]); - long week = Rows.number(deliveries.paidSince(courier, now - 7 * DAY_MILLIS)); + long week = Rows.number(deliveries.paidSince(courier, Instant.ofEpochMilli(now - 7 * DAY_MILLIS))); Object[] total = deliveries.paidTotals(courier); int count = total == null ? 0 : (int) Rows.number(total[0]); long all = total == null ? 0L : Rows.number(total[1]); @@ -305,7 +306,7 @@ private static CourierDto toDto(Profile profile, CourierApplication application, double rating = 5d; long lastSeen = 0L; if (car != null) { - lastSeen = car.getLastSeen(); + lastSeen = car.getLastSeen().toEpochMilli(); // On line means said so and heard from lately; see Matcher. online = car.isOnline() && System.currentTimeMillis() - lastSeen < Matcher.FRESH_MILLIS; diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/courier/Earnings.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/courier/Earnings.java index d082b078f0c..a345522114d 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/courier/Earnings.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/courier/Earnings.java @@ -48,6 +48,7 @@ import com.codenameone.examples.savor.order.Quotes; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -115,16 +116,16 @@ public EarningsSummaryDto summary(String courier) throws IOException { long monthStart = today - 29 * Days.MILLIS; long weekStart = today - 6 * Days.MILLIS; List done = deliveries.findByCourierAndStateAndUpdatedAtGreaterThanEqual(courier, - DeliveryState.COMPLETED, monthStart); + DeliveryState.COMPLETED, Instant.ofEpochMilli(monthStart)); // A card tip is on its delivery from the moment it is asked for, and is // still there when the processor never answered. Only one whose charge // is on record is earned, here as in the balance: otherwise a day's // total would show money that cannot be cashed out. Set charged = new HashSet( - deliveries.tipChargedSince(courier, monthStart)); + deliveries.tipChargedSince(courier, Instant.ofEpochMilli(monthStart))); for (int iter = 0; iter < done.size(); iter++) { Delivery delivery = done.get(iter); - long at = delivery.getUpdatedAt(); + long at = delivery.getUpdatedAt().toEpochMilli(); boolean tipped = "cash".equals(delivery.getMethodId()) || charged.contains(delivery.getId()); // The fare likewise counts only once it is paid, as in the balance: // a card charge that failed, was refunded or has not come back is @@ -197,7 +198,7 @@ public PayoutDto cashOut(String courier) throws IOException { row.setCourier(courier); row.setAmountCents(amount); row.setStatus("paid"); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); row.setDestination(account.getBankName() + " ****" + account.getLast4()); payouts.insert(row); return toDto(row); @@ -297,6 +298,6 @@ private static PayoutAccountDto toDto(PayoutAccount row) { private static PayoutDto toDto(Payout row) { return new PayoutDto(row.getId(), row.getAmountCents(), row.getStatus(), - row.getCreatedAt(), row.getDestination()); + row.getCreatedAt().toEpochMilli(), row.getDestination()); } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/delivery/Deliveries.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/delivery/Deliveries.java index 0e556c6e391..8c5bab31928 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/delivery/Deliveries.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/delivery/Deliveries.java @@ -56,6 +56,7 @@ import com.codenameone.examples.savor.repository.DeliveryRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -177,9 +178,9 @@ public void dispatch(CustomerOrder order, Restaurant restaurant) throws IOExcept delivery.setMethodLabel(order.getMethodLabel()); delivery.setPaymentStatus(order.getPaymentStatus()); delivery.setNote(order.getNote()); - delivery.setRequestedAt(now); - delivery.setUpdatedAt(now); - delivery.setSearchUntil(now + searchMillis); + delivery.setRequestedAt(Instant.ofEpochMilli(now)); + delivery.setUpdatedAt(Instant.ofEpochMilli(now)); + delivery.setSearchUntil(Instant.ofEpochMilli(now + searchMillis)); deliveries.insert(delivery); event(order.getId(), DeliveryState.REQUESTED, ""); } @@ -279,7 +280,7 @@ private Delivery finish(String courier, String id) throws IOException { Delivery delivery = owned(id, COURIER, courier); move(id, DeliveryState.COMPLETED, courier, COURIER, null, null); if (orders.deliver(id, OrderStateMachine.sources(OrderState.DELIVERED), - OrderState.DELIVERED, System.currentTimeMillis()) == 1) { + OrderState.DELIVERED, Instant.now()) == 1) { orderEvents.record(id, OrderState.DELIVERED, courier); } return delivery; @@ -334,13 +335,13 @@ public void settleLeftBehind() throws IOException { @Transactional(readOnly = true) private List unsettled(long after, long before) { - return deliveries.unsettled(after, before, new PageRequest(0, 50)); + return deliveries.unsettled(Instant.ofEpochMilli(after), Instant.ofEpochMilli(before), new PageRequest(0, 50)); } @Transactional private Change settled(String courier, String id, String status) throws IOException { deliveries.paymentStatus(id, status); - orders.paymentStatus(id, status, System.currentTimeMillis()); + orders.paymentStatus(id, status, Instant.now()); Delivery delivery = find(id); return new Change(id, delivery.getState(), delivery.getCustomer(), delivery.getCourier(), "", toDto(delivery, courier, new HashMap())); @@ -359,7 +360,7 @@ public DeliveryDto cancelByCourier(String courier, String id) throws IOException private Change giveUp(String courier, String id) throws IOException { Delivery delivery = owned(id, COURIER, courier); if (deliveries.giveBack(id, TAKEN_NOT_STARTED, DeliveryState.REQUESTED, - System.currentTimeMillis(), courier, "") != 1) { + Instant.now(), courier, "") != 1) { throw new ResponseStatusException(409, "That delivery is " + describe(find(id).getState())); } @@ -394,7 +395,7 @@ private Change step(String courier, String id, DeliveryState to) throws IOExcept // The courier has the food: the order is picked up in the same // transaction, and only once the kitchen said it is ready. if (orders.move(id, OrderStateMachine.sources(OrderState.PICKED_UP), - OrderState.PICKED_UP, System.currentTimeMillis()) != 1) { + OrderState.PICKED_UP, Instant.now()) != 1) { throw new ResponseStatusException(409, "The kitchen has not marked it ready yet"); } orderEvents.record(id, OrderState.PICKED_UP, courier); @@ -494,17 +495,17 @@ private Change choose(String id, String[] chosen) throws IOException { return null; } long now = System.currentTimeMillis(); - if (now > delivery.getSearchUntil()) { + if (now > delivery.getSearchUntil().toEpochMilli()) { if (!tryMove(id, DeliveryState.NO_COURIERS, "", null, null, null)) { return null; } if (orders.end(id, OrderStateMachine.sources(OrderState.NO_COURIERS), - OrderState.NO_COURIERS, "No courier was free to bring it", now) == 1) { + OrderState.NO_COURIERS, "No courier was free to bring it", Instant.ofEpochMilli(now)) == 1) { orderEvents.record(id, OrderState.NO_COURIERS, ""); } return new Change(id, DeliveryState.NO_COURIERS, delivery.getCustomer(), "", "", null); } - chosen[0] = matcher.pick(delivery, now - delivery.getRequestedAt()); + chosen[0] = matcher.pick(delivery, now - delivery.getRequestedAt().toEpochMilli()); return null; } @@ -535,7 +536,7 @@ Change offer(String id, String courier) throws IOException { return null; } long now = System.currentTimeMillis(); - if (!matcher.fits(delivery, courier, now - delivery.getRequestedAt())) { + if (!matcher.fits(delivery, courier, now - delivery.getRequestedAt().toEpochMilli())) { return null; } return tryMove(id, DeliveryState.OFFERED, "", null, courier, Long.valueOf(now + offerMillis)) @@ -584,7 +585,7 @@ public void tick() throws IOException { @Transactional(readOnly = true) private List lapsedOffers(long now) throws IOException { - return deliveries.findByStateAndOfferExpiresAtLessThan(DeliveryState.OFFERED, now); + return deliveries.findByStateAndOfferExpiresAtLessThan(DeliveryState.OFFERED, Instant.ofEpochMilli(now)); } @Transactional(readOnly = true) @@ -723,10 +724,11 @@ private boolean tryMove(String id, DeliveryState to, String actor, String ownerF if (sources.length == 0) { return false; } - long now = System.currentTimeMillis(); + Instant now = Instant.now(); int moved; if (newOfferExpiresAt != null) { - moved = deliveries.offer(id, sources, to, now, newCourier, newOfferExpiresAt.longValue()); + moved = deliveries.offer(id, sources, to, now, newCourier, + Instant.ofEpochMilli(newOfferExpiresAt.longValue())); } else if (CUSTOMER.equals(ownerField)) { moved = deliveries.moveAsCustomer(id, sources, to, now, actor); } else if (!COURIER.equals(ownerField)) { @@ -754,7 +756,7 @@ private void event(String id, DeliveryState state, String actor) throws IOExcept event.setDeliveryId(id); event.setState(state); event.setActor(actor); - event.setCreatedAt(System.currentTimeMillis()); + event.setCreatedAt(Instant.now()); events.insert(event); } @@ -888,7 +890,7 @@ private DeliveryDto toDto(Delivery delivery, String viewer, Map } if (offered) { offerExpiresInSeconds = (int) Math.max(0L, - (delivery.getOfferExpiresAt() - System.currentTimeMillis()) / 1000L); + (delivery.getOfferExpiresAt().toEpochMilli() - System.currentTimeMillis()) / 1000L); } long fareCents = delivery.getFareCents(); long tip = delivery.getTipCents(); @@ -921,8 +923,8 @@ private DeliveryDto toDto(Delivery delivery, String viewer, Map delivery.getCurrency(), delivery.getDistanceMeters(), delivery.getDurationSeconds(), - delivery.getRequestedAt(), - delivery.getUpdatedAt(), + delivery.getRequestedAt().toEpochMilli(), + delivery.getUpdatedAt().toEpochMilli(), delivery.getStars(), delivery.getPaymentStatus(), offerExpiresInSeconds, diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/delivery/Matcher.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/delivery/Matcher.java index 3d632f9b9a7..226f645a0e8 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/delivery/Matcher.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/delivery/Matcher.java @@ -37,6 +37,7 @@ import com.codenameone.examples.savor.repository.DeliveryPassedRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -132,7 +133,7 @@ private List free(double lat, double lng, double radiusMeters) throws double dLat = radiusMeters / Geo.METERS_PER_DEGREE; double shrink = Math.max(0.01d, Math.cos(Math.toRadians(lat))); double dLng = radiusMeters / (Geo.METERS_PER_DEGREE * shrink); - List boxed = couriers.freeInBox(System.currentTimeMillis() - FRESH_MILLIS, + List boxed = couriers.freeInBox(Instant.now().minusMillis(FRESH_MILLIS), lat - dLat, lat + dLat, lng - dLng, lng + dLng, Applications.APPROVED, WITH_DELIVERY); List inReach = new ArrayList(); List names = new ArrayList(); diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/ClosedAccount.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/ClosedAccount.java index 14f1392da29..07f19a9c45c 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/ClosedAccount.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/ClosedAccount.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// What is left of an account that was closed: the hash of its e-mail, kept so /// that the address cannot be registered again. @@ -31,7 +32,7 @@ public class ClosedAccount { private String usernameHash = ""; @Column(nullable = false) - private long closedAt; + private Instant closedAt = Instant.EPOCH; public ClosedAccount() { } @@ -44,11 +45,11 @@ public void setUsernameHash(String usernameHash) { this.usernameHash = usernameHash; } - public long getClosedAt() { + public Instant getClosedAt() { return closedAt; } - public void setClosedAt(long closedAt) { + public void setClosedAt(Instant closedAt) { this.closedAt = closedAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierApplication.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierApplication.java index dabb9e342e9..1c5662f6f58 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierApplication.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierApplication.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An account's application to deliver, and what became of it. @Entity @@ -63,13 +64,13 @@ public class CourierApplication { private String rejectionReason = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) - private long submittedAt; + private Instant submittedAt = Instant.EPOCH; @Column(nullable = false) - private long reviewedAt; + private Instant reviewedAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(190)") private String reviewedBy = ""; @@ -173,27 +174,27 @@ public void setRejectionReason(String rejectionReason) { this.rejectionReason = rejectionReason; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public long getSubmittedAt() { + public Instant getSubmittedAt() { return submittedAt; } - public void setSubmittedAt(long submittedAt) { + public void setSubmittedAt(Instant submittedAt) { this.submittedAt = submittedAt; } - public long getReviewedAt() { + public Instant getReviewedAt() { return reviewedAt; } - public void setReviewedAt(long reviewedAt) { + public void setReviewedAt(Instant reviewedAt) { this.reviewedAt = reviewedAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierDocument.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierDocument.java index 51f6214e105..cb5f0d610d7 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierDocument.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierDocument.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A document an applicant uploaded, one of each kind. `data` is the file in /// Base64, which is text on every database. @@ -41,7 +42,7 @@ public class CourierDocument { private String status = ""; @Column(nullable = false) - private long uploadedAt; + private Instant uploadedAt = Instant.EPOCH; @Column(nullable = false) private String data = ""; @@ -81,11 +82,11 @@ public void setStatus(String status) { this.status = status; } - public long getUploadedAt() { + public Instant getUploadedAt() { return uploadedAt; } - public void setUploadedAt(long uploadedAt) { + public void setUploadedAt(Instant uploadedAt) { this.uploadedAt = uploadedAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierState.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierState.java index 85d1049a05c..6401313002d 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierState.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CourierState.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// Where a courier's car is, whether they are on line, and what customers made of them. @Entity @@ -42,7 +43,7 @@ public class CourierState { private double heading; @Column(nullable = false) - private long lastSeen; + private Instant lastSeen = Instant.EPOCH; @Column(nullable = false) private long ratingSum; @@ -98,11 +99,11 @@ public void setHeading(double heading) { this.heading = heading; } - public long getLastSeen() { + public Instant getLastSeen() { return lastSeen; } - public void setLastSeen(long lastSeen) { + public void setLastSeen(Instant lastSeen) { this.lastSeen = lastSeen; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CustomerOrder.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CustomerOrder.java index d34529b2739..b1f2b1494c9 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CustomerOrder.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/CustomerOrder.java @@ -23,6 +23,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An order: what a customer bought from one restaurant, what it cost, and where /// it stands. Its lines, prices and address are copied in when it is placed, so a @@ -107,19 +108,19 @@ public class CustomerOrder { private int prepMinutes; @Column(nullable = false) - private long placedAt; + private Instant placedAt = Instant.EPOCH; @Column(nullable = false) - private long acceptedAt; + private Instant acceptedAt = Instant.EPOCH; @Column(nullable = false) - private long readyAt; + private Instant readyAt = Instant.EPOCH; @Column(nullable = false) - private long deliveredAt; + private Instant deliveredAt = Instant.EPOCH; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(255)") private String reason = ""; @@ -330,43 +331,43 @@ public void setPrepMinutes(int prepMinutes) { this.prepMinutes = prepMinutes; } - public long getPlacedAt() { + public Instant getPlacedAt() { return placedAt; } - public void setPlacedAt(long placedAt) { + public void setPlacedAt(Instant placedAt) { this.placedAt = placedAt; } - public long getAcceptedAt() { + public Instant getAcceptedAt() { return acceptedAt; } - public void setAcceptedAt(long acceptedAt) { + public void setAcceptedAt(Instant acceptedAt) { this.acceptedAt = acceptedAt; } - public long getReadyAt() { + public Instant getReadyAt() { return readyAt; } - public void setReadyAt(long readyAt) { + public void setReadyAt(Instant readyAt) { this.readyAt = readyAt; } - public long getDeliveredAt() { + public Instant getDeliveredAt() { return deliveredAt; } - public void setDeliveredAt(long deliveredAt) { + public void setDeliveredAt(Instant deliveredAt) { this.deliveredAt = deliveredAt; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Delivery.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Delivery.java index 174d2eb5ea3..64075d9c942 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Delivery.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Delivery.java @@ -22,6 +22,7 @@ import com.codename1.annotations.Entity; import com.codename1.annotations.Id; import com.codenameone.examples.savor.api.DeliveryState; +import java.time.Instant; // tag::savor-entity[] /// A delivery, from the request to its end. @@ -75,16 +76,16 @@ public class Delivery { private double durationSeconds; @Column(nullable = false) - private long requestedAt; + private Instant requestedAt = Instant.EPOCH; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; @Column(nullable = false) - private long offerExpiresAt; + private Instant offerExpiresAt = Instant.EPOCH; @Column(nullable = false) - private long searchUntil; + private Instant searchUntil = Instant.EPOCH; @Column(nullable = false, type = "SMALLINT") private int stars; @@ -225,35 +226,35 @@ public void setDurationSeconds(double durationSeconds) { this.durationSeconds = durationSeconds; } - public long getRequestedAt() { + public Instant getRequestedAt() { return requestedAt; } - public void setRequestedAt(long requestedAt) { + public void setRequestedAt(Instant requestedAt) { this.requestedAt = requestedAt; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } - public long getOfferExpiresAt() { + public Instant getOfferExpiresAt() { return offerExpiresAt; } - public void setOfferExpiresAt(long offerExpiresAt) { + public void setOfferExpiresAt(Instant offerExpiresAt) { this.offerExpiresAt = offerExpiresAt; } - public long getSearchUntil() { + public Instant getSearchUntil() { return searchUntil; } - public void setSearchUntil(long searchUntil) { + public void setSearchUntil(Instant searchUntil) { this.searchUntil = searchUntil; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/DeliveryActivity.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/DeliveryActivity.java index b44ee60cffa..1e8b9d4eebf 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/DeliveryActivity.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/DeliveryActivity.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// The Live Activity a customer's phone shows a delivery in, while the delivery lasts. @Entity @@ -38,12 +39,12 @@ public class DeliveryActivity { /// When the server last sent it a state, for spacing out the updates. @Column(nullable = false) - private long sentAt; + private Instant sentAt = Instant.EPOCH; /// When its delivery ended, 0 while the delivery lasts. An ended activity is kept /// until the phone has been told to end it. @Column(nullable = false) - private long endedAt; + private Instant endedAt = Instant.EPOCH; public DeliveryActivity() { } @@ -72,19 +73,19 @@ public void setActivityId(String activityId) { this.activityId = activityId; } - public long getSentAt() { + public Instant getSentAt() { return sentAt; } - public void setSentAt(long sentAt) { + public void setSentAt(Instant sentAt) { this.sentAt = sentAt; } - public long getEndedAt() { + public Instant getEndedAt() { return endedAt; } - public void setEndedAt(long endedAt) { + public void setEndedAt(Instant endedAt) { this.endedAt = endedAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/DeliveryEvent.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/DeliveryEvent.java index 53e646b615c..1ac81efdafb 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/DeliveryEvent.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/DeliveryEvent.java @@ -22,6 +22,7 @@ import com.codename1.annotations.Entity; import com.codename1.annotations.Id; import com.codenameone.examples.savor.api.DeliveryState; +import java.time.Instant; /// One change of a delivery's state: what it became, who made it so, and when. @Entity @@ -40,7 +41,7 @@ public class DeliveryEvent { private String actor = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public DeliveryEvent() { } @@ -77,11 +78,11 @@ public void setActor(String actor) { this.actor = actor; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Favorite.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Favorite.java index 0c6e5d11b64..6161bf14cfd 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Favorite.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Favorite.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A restaurant a customer keeps, keyed by `Identifier.of(username, restaurantId)`. @Entity @@ -34,7 +35,7 @@ public class Favorite { private String restaurantId = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public Favorite() { } @@ -55,11 +56,11 @@ public void setRestaurantId(String restaurantId) { this.restaurantId = restaurantId; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/LiveTicket.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/LiveTicket.java index 4e0f5fecd38..801de0c7994 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/LiveTicket.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/LiveTicket.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A ticket for one connection to the live channel, as its hash. @Entity @@ -33,7 +34,7 @@ public class LiveTicket { private String username = ""; @Column(nullable = false) - private long expiresAt; + private Instant expiresAt = Instant.EPOCH; public LiveTicket() { } @@ -54,11 +55,11 @@ public void setUsername(String username) { this.username = username; } - public long getExpiresAt() { + public Instant getExpiresAt() { return expiresAt; } - public void setExpiresAt(long expiresAt) { + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/ModerationEvent.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/ModerationEvent.java index 0ad8aeb3fdb..d8c37f92589 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/ModerationEvent.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/ModerationEvent.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One thing an admin did to an account, and why. Written once, never changed. @Entity @@ -33,7 +34,7 @@ public class ModerationEvent { private String username = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(190)") private String actor = ""; @@ -63,11 +64,11 @@ public void setUsername(String username) { this.username = username; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/OrderEvent.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/OrderEvent.java index 94d091face4..a9a98afadd0 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/OrderEvent.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/OrderEvent.java @@ -23,6 +23,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A change of an order's state: what it became, who made it, and when. @Entity @@ -41,7 +42,7 @@ public class OrderEvent { private String actor = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public OrderEvent() { } @@ -78,11 +79,11 @@ public void setActor(String actor) { this.actor = actor; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Payment.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Payment.java index 8157760cf44..5c4cc53be74 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Payment.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Payment.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// What a completed delivery was charged, and what was given back. @Entity @@ -42,7 +43,7 @@ public class Payment { private String providerRef = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(64)") private String tipRef = ""; @@ -57,7 +58,7 @@ public class Payment { private String refundReason = ""; @Column(nullable = false) - private long refundedAt; + private Instant refundedAt = Instant.EPOCH; public Payment() { } @@ -102,11 +103,11 @@ public void setProviderRef(String providerRef) { this.providerRef = providerRef; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } @@ -142,11 +143,11 @@ public void setRefundReason(String refundReason) { this.refundReason = refundReason; } - public long getRefundedAt() { + public Instant getRefundedAt() { return refundedAt; } - public void setRefundedAt(long refundedAt) { + public void setRefundedAt(Instant refundedAt) { this.refundedAt = refundedAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PaymentMethod.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PaymentMethod.java index 8edddcfdf35..4edbb85fabc 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PaymentMethod.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PaymentMethod.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A saved card: what the provider calls it and what to show for it. The /// number itself is never here. @@ -52,7 +53,7 @@ public class PaymentMethod { private boolean preferred; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public PaymentMethod() { } @@ -121,11 +122,11 @@ public void setPreferred(boolean preferred) { this.preferred = preferred; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PaymentSetup.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PaymentSetup.java index 410658a37e0..5b0757fee9c 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PaymentSetup.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PaymentSetup.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A card being added on the provider's page, until the browser comes back. @Entity @@ -36,7 +37,7 @@ public class PaymentSetup { private String reference = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) private boolean completed; @@ -68,11 +69,11 @@ public void setReference(String reference) { this.reference = reference; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Payout.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Payout.java index 295beb14887..69c99a0ff6b 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Payout.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Payout.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One payment of earnings to a courier. @Entity @@ -39,7 +40,7 @@ public class Payout { private String status = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(120)") private String destination = ""; @@ -79,11 +80,11 @@ public void setStatus(String status) { this.status = status; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PhoneCode.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PhoneCode.java index 87115e9f825..db6ea1e2477 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PhoneCode.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PhoneCode.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// The verification code an account was last sent, as its hash. @Entity @@ -33,20 +34,20 @@ public class PhoneCode { private String codeHash = ""; @Column(nullable = false) - private long expiresAt; + private Instant expiresAt = Instant.EPOCH; @Column(nullable = false) private int attempts; @Column(nullable = false) - private long sentAt; + private Instant sentAt = Instant.EPOCH; /// The code sent before this one, while it is still good, or empty. @Column(nullable = false, type = "VARCHAR(64)") private String previousHash = ""; @Column(nullable = false) - private long previousExpiresAt; + private Instant previousExpiresAt = Instant.EPOCH; /// The guesses already taken at the code before, which keeps the budget /// it had rather than starting a new one when another code is sent. @@ -72,11 +73,11 @@ public void setCodeHash(String codeHash) { this.codeHash = codeHash; } - public long getExpiresAt() { + public Instant getExpiresAt() { return expiresAt; } - public void setExpiresAt(long expiresAt) { + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } @@ -88,11 +89,11 @@ public void setAttempts(int attempts) { this.attempts = attempts; } - public long getSentAt() { + public Instant getSentAt() { return sentAt; } - public void setSentAt(long sentAt) { + public void setSentAt(Instant sentAt) { this.sentAt = sentAt; } @@ -104,11 +105,11 @@ public void setPreviousHash(String previousHash) { this.previousHash = previousHash; } - public long getPreviousExpiresAt() { + public Instant getPreviousExpiresAt() { return previousExpiresAt; } - public void setPreviousExpiresAt(long previousExpiresAt) { + public void setPreviousExpiresAt(Instant previousExpiresAt) { this.previousExpiresAt = previousExpiresAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Photo.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Photo.java index 10c7a383d9a..b26494ea2ca 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Photo.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Photo.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A restaurant's or a dish's picture: the bytes of a JPEG or a PNG. @Entity @@ -36,7 +37,7 @@ public class Photo { private String contentType = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) private byte[] data = new byte[0]; @@ -68,11 +69,11 @@ public void setContentType(String contentType) { this.contentType = contentType; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Pricing.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Pricing.java index 5fe90ebfb8e..ab0cea02412 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Pricing.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Pricing.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// What an order costs on top of its food, and what the service keeps of it. /// There is one row; see V6. @@ -55,7 +56,7 @@ public class Pricing { private double commissionPercent; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(190)") private String updatedBy = ""; @@ -135,11 +136,11 @@ public void setCommissionPercent(double commissionPercent) { this.commissionPercent = commissionPercent; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Profile.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Profile.java index d9bdfef5872..d4c63522b49 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Profile.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Profile.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An account's profile: who it is to the people it deliveries with. /// @@ -48,7 +49,7 @@ public class Profile { private String plate = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(8)") private String language = "en"; @@ -110,11 +111,11 @@ public void setPlate(String plate) { this.plate = plate; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Promo.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Promo.java index 384b8cf25d7..0d07ce19894 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Promo.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Promo.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A code a customer types at checkout: a percentage or an amount off the food, /// for an order of at least `minimumCents`, once per account. @@ -43,7 +44,7 @@ public class Promo { private boolean active; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public Promo() { } @@ -88,11 +89,11 @@ public void setActive(boolean active) { this.active = active; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PushDevice.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PushDevice.java index d5c941dde26..ec59e720d4a 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PushDevice.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/PushDevice.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A device an account is sent push notifications on. /// @@ -46,7 +47,7 @@ public class PushDevice { private String platform = ""; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; public PushDevice() { } @@ -91,11 +92,11 @@ public void setPlatform(String platform) { this.platform = platform; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Restaurant.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Restaurant.java index cd0cf9878ba..23b931465eb 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Restaurant.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/Restaurant.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A restaurant on the service: listed once an admin approves it, and taking /// orders while it is open and its staff have not paused it. @@ -85,10 +86,10 @@ public class Restaurant { private String reason = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; public Restaurant() { } @@ -245,19 +246,19 @@ public void setReason(String reason) { this.reason = reason; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/SavedAddress.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/SavedAddress.java index 2065edf1f35..43a6b2f66fa 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/SavedAddress.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/domain/SavedAddress.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A place a customer has kept to be delivered to. @Entity @@ -48,7 +49,7 @@ public class SavedAddress { private String note = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public SavedAddress() { } @@ -109,11 +110,11 @@ public void setNote(String note) { this.note = note; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/live/LiveTickets.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/live/LiveTickets.java index 8cf7d0215b7..c4e4d3a167f 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/live/LiveTickets.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/live/LiveTickets.java @@ -28,6 +28,7 @@ import com.codenameone.examples.savor.repository.LiveTicketRepository; import java.io.IOException; +import java.time.Instant; /// Tickets for the live channel. /// @@ -58,7 +59,7 @@ public TicketDto issue(String username) throws IOException { LiveTicket row = new LiveTicket(); row.setTicketHash(Ids.sha256(ticket)); row.setUsername(username); - row.setExpiresAt(System.currentTimeMillis() + TICKET_SECONDS * 1000L); + row.setExpiresAt(Instant.ofEpochMilli(System.currentTimeMillis() + TICKET_SECONDS * 1000L)); tickets.insert(row); return new TicketDto(ticket, TICKET_SECONDS); } @@ -78,7 +79,7 @@ public String redeem(String ticket) throws IOException { return null; } String username = row.getUsername(); - long expiresAt = row.getExpiresAt(); + long expiresAt = row.getExpiresAt().toEpochMilli(); // One delete statement: the count it answers is what says this // connection, and not another presenting the same ticket, used it. int removed = tickets.deleteByTicketHash(hash); @@ -92,7 +93,7 @@ public String redeem(String ticket) throws IOException { @Scheduled(fixedDelay = 60000, initialDelay = 60000) @Transactional public void sweep() throws IOException { - tickets.deleteByExpiresAtLessThan(System.currentTimeMillis()); + tickets.deleteByExpiresAtLessThan(Instant.now()); } /// Forgets the tickets of an account that is being closed. diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/onboarding/Applications.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/onboarding/Applications.java index 64e1c6652ac..ce62acc5b13 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/onboarding/Applications.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/onboarding/Applications.java @@ -30,6 +30,7 @@ import com.codename1.orm.session.Identifier; import com.codenameone.examples.savor.Days; import com.codenameone.examples.savor.Roles; +import com.codenameone.examples.savor.Rows; import com.codenameone.examples.savor.Text; import com.codenameone.examples.savor.account.Moderation; import com.codenameone.examples.savor.api.DocumentContentDto; @@ -44,6 +45,7 @@ import com.codenameone.examples.savor.repository.ProfileRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -244,13 +246,13 @@ public CourierApplicationDto upload(String username, DocumentUploadDto upload) long now = System.currentTimeMillis(); // Replaced with a statement where there is one already, so the picture // it held is not read only to be overwritten. - if (documents.replace(username, kind, type, "uploaded", now, data) == 0) { + if (documents.replace(username, kind, type, "uploaded", Instant.ofEpochMilli(now), data) == 0) { CourierDocument document = new CourierDocument(); document.setUsername(username); document.setKind(kind); document.setContentType(type); document.setStatus("uploaded"); - document.setUploadedAt(now); + document.setUploadedAt(Instant.ofEpochMilli(now)); document.setData(data); documents.insert(document); } @@ -310,7 +312,7 @@ public CourierApplicationDto submit(String username) throws IOException { throw new ResponseStatusException(400, what.toString()); } // Held to the status it was read in: handed in twice, it is handed in once. - applications.submit(username, was, PENDING, System.currentTimeMillis()); + applications.submit(username, was, PENDING, Instant.now()); return get(username); } @@ -424,7 +426,7 @@ public void grant(String by, String username) throws IOException { applications.insert(blank(username, APPROVED, "", "")); return; } - applications.approveUnlessApproved(username, APPROVED, System.currentTimeMillis(), by); + applications.approveUnlessApproved(username, APPROVED, Instant.now(), by); } /// Takes the approval back, when an admin withdraws the COURIER role. The @@ -432,7 +434,7 @@ public void grant(String by, String username) throws IOException { @Transactional public void withdraw(String by, String username) throws IOException { applications.move(username, APPROVED, REJECTED, "Onboarding was withdrawn by an admin", - System.currentTimeMillis(), by); + Instant.now(), by); } /// Everything kept about an account's application, for an account being @@ -453,7 +455,7 @@ private void decide(String by, String username, String to, String reason) if (find(username) == null) { throw new ResponseStatusException(404, "No such application"); } - if (applications.move(username, PENDING, to, reason, System.currentTimeMillis(), by) + if (applications.move(username, PENDING, to, reason, Instant.now(), by) != 1) { throw new ResponseStatusException(409, "That application is not waiting for an answer"); } @@ -534,8 +536,8 @@ private static CourierApplication blank(String username, String status, String v application.setStatus(status); application.setVehicleModel(vehicle.length() > 40 ? vehicle.substring(0, 40) : vehicle); application.setVehiclePlate(plate); - application.setCreatedAt(now); - application.setReviewedAt(APPROVED.equals(status) ? now : 0L); + application.setCreatedAt(Instant.ofEpochMilli(now)); + application.setReviewedAt(APPROVED.equals(status) ? Instant.ofEpochMilli(now) : Instant.EPOCH); return application; } @@ -566,8 +568,7 @@ private static CourierApplicationDto toDto(String username, String name, Object[] stored = documents.get(iter); if (KINDS[kind].equals(stored[from])) { status = (String) stored[from + 1]; - Object at = stored[from + 2]; - uploadedAt = at instanceof Number ? ((Number) at).longValue() : 0L; + uploadedAt = Rows.millis(stored[from + 2]); } } listed.add(new DocumentDto(KINDS[kind], status, uploadedAt)); @@ -581,7 +582,7 @@ private static CourierApplicationDto toDto(String username, String name, row.getDateOfBirth(), row.getLicenceNumber(), row.getLicenceExpiry(), row.getVehicleMake(), row.getVehicleModel(), row.getVehicleYear(), row.getVehicleColor(), row.getVehiclePlate(), listed, - row.getRejectionReason(), row.getSubmittedAt(), row.getReviewedAt(), + row.getRejectionReason(), row.getSubmittedAt().toEpochMilli(), row.getReviewedAt().toEpochMilli(), row.getReviewedBy()); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Addresses.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Addresses.java index 48261e9e938..eecfc124c9b 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Addresses.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Addresses.java @@ -29,6 +29,7 @@ import com.codenameone.examples.savor.repository.ProfileRepository; import com.codenameone.examples.savor.repository.SavedAddressRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -77,7 +78,7 @@ public SavedAddressDto save(String username, SavedAddressDto form) throws IOExce row = new SavedAddress(); row.setId(Ids.next()); row.setUsername(username); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); } row.setLabel(Text.required(form.label(), 40, "a name for the place")); row.setAddress(Text.required(form.address(), 255, "the address")); diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/DemoKitchen.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/DemoKitchen.java index de13aa5c456..1d8c20aae98 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/DemoKitchen.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/DemoKitchen.java @@ -28,6 +28,7 @@ import com.codenameone.examples.savor.repository.CustomerOrderRepository; import com.codenameone.examples.savor.repository.RestaurantStaffRepository; import java.io.IOException; +import java.time.Instant; import java.util.List; /// The kitchens of the demo restaurants nobody runs, on a development server: @@ -62,7 +63,7 @@ public void cook() throws IOException { return; } long now = System.currentTimeMillis(); - List waiting = unattended(OrderState.PLACED, now - ACCEPT_AFTER_MILLIS); + List waiting = unattended(OrderState.PLACED, Instant.ofEpochMilli(now - ACCEPT_AFTER_MILLIS)); for (int iter = 0; iter < waiting.size(); iter++) { CustomerOrder order = waiting.get(iter); try { @@ -72,7 +73,7 @@ public void cook() throws IOException { // Cancelled or turned down in the meantime. } } - List cooking = unattended(OrderState.ACCEPTED, now - READY_AFTER_MILLIS); + List cooking = unattended(OrderState.ACCEPTED, Instant.ofEpochMilli(now - READY_AFTER_MILLIS)); for (int iter = 0; iter < cooking.size(); iter++) { CustomerOrder order = cooking.get(iter); try { @@ -85,7 +86,7 @@ public void cook() throws IOException { /// Orders in `state` since before `before` at restaurants with no staff. @Transactional(readOnly = true) - private List unattended(OrderState state, long before) { + private List unattended(OrderState state, Instant before) { List rows = OrderState.PLACED == state ? orders.findByStateAndPlacedAtLessThan(state, before) : orders.findByStateAndAcceptedAtLessThan(state, before); diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/DemoOrders.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/DemoOrders.java index 82a3b972b2f..88392e3bbc0 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/DemoOrders.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/DemoOrders.java @@ -49,6 +49,7 @@ import com.codenameone.examples.savor.repository.PayoutRepository; import com.codenameone.examples.savor.repository.RestaurantRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -226,12 +227,12 @@ public void seed(String[] customers, String[] couriers) throws IOException { order.setPaymentStatus(delivered ? Payments.PAID : cash ? Payments.PENDING : Payments.RELEASED); order.setPrepMinutes(kitchen.getPrepMinutes()); - order.setPlacedAt(at); - order.setUpdatedAt(ended); + order.setPlacedAt(Instant.ofEpochMilli(at)); + order.setUpdatedAt(Instant.ofEpochMilli(ended)); order.setAcceptedAt(OrderState.REJECTED == state - || OrderState.CANCELLED_BY_CUSTOMER == state ? 0L : accepted); - order.setReadyAt(delivered ? ready : 0L); - order.setDeliveredAt(delivered ? ended : 0L); + || OrderState.CANCELLED_BY_CUSTOMER == state ? Instant.EPOCH : Instant.ofEpochMilli(accepted)); + order.setReadyAt(delivered ? Instant.ofEpochMilli(ready) : Instant.EPOCH); + order.setDeliveredAt(delivered ? Instant.ofEpochMilli(ended) : Instant.EPOCH); order.setReason(OrderState.REJECTED == state ? "Out of ingredients" : OrderState.NO_COURIERS == state ? "No courier was free to bring it" : OrderState.CANCELLED_BY_CUSTOMER == state ? "Cancelled by the customer" @@ -270,9 +271,9 @@ public void seed(String[] customers, String[] couriers) throws IOException { delivery.setCurrency(pricing.currency()); delivery.setDistanceMeters(meters); delivery.setDurationSeconds(meters / Quotes.METERS_PER_SECOND); - delivery.setRequestedAt(accepted); - delivery.setUpdatedAt(ended); - delivery.setSearchUntil(accepted + 900000L); + delivery.setRequestedAt(Instant.ofEpochMilli(accepted)); + delivery.setUpdatedAt(Instant.ofEpochMilli(ended)); + delivery.setSearchUntil(Instant.ofEpochMilli(accepted + 900000L)); delivery.setStars(given); delivery.setPaymentStatus(delivered ? Payments.PAID : Payments.PENDING); delivery.setMethodId(method[0]); @@ -300,7 +301,7 @@ public void seed(String[] customers, String[] couriers) throws IOException { payment.setStatus(Payments.PAID); payment.setProviderRef(cash ? Payments.CASH : "sim_ch_order-" + id); payment.setTipRef(""); - payment.setCreatedAt(ended); + payment.setCreatedAt(Instant.ofEpochMilli(ended)); paid.insert(payment); lastSeen[courierIndex] = Math.max(lastSeen[courierIndex], ended); if (ended < now - 7L * Days.MILLIS) { @@ -324,7 +325,7 @@ public void seed(String[] customers, String[] couriers) throws IOException { } state.setLat(real(iter % DOORS.length, 1)); state.setLng(real(iter % DOORS.length, 2)); - state.setLastSeen(lastSeen[iter]); + state.setLastSeen(Instant.ofEpochMilli(lastSeen[iter])); state.setRatingSum(stars[iter]); state.setRatingCount(rated[iter]); if (first) { @@ -343,7 +344,7 @@ public void seed(String[] customers, String[] couriers) throws IOException { payout.setCourier(couriers[iter]); payout.setAmountCents(earnedEarlier[iter]); payout.setStatus("paid"); - payout.setCreatedAt(now - 7L * Days.MILLIS); + payout.setCreatedAt(Instant.ofEpochMilli(now - 7L * Days.MILLIS)); payout.setDestination("Bay Credit Union ****67" + (10 + iter)); payouts.insert(payout); } @@ -357,7 +358,7 @@ private void orderEvent(String order, OrderState state, String actor, long at) event.setOrderId(order); event.setState(state); event.setActor(actor); - event.setCreatedAt(at); + event.setCreatedAt(Instant.ofEpochMilli(at)); orderEvents.insert(event); } @@ -368,7 +369,7 @@ private void deliveryEvent(String delivery, DeliveryState state, String actor, l event.setDeliveryId(delivery); event.setState(state); event.setActor(actor); - event.setCreatedAt(at); + event.setCreatedAt(Instant.ofEpochMilli(at)); deliveryEvents.insert(event); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/OrderEvents.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/OrderEvents.java index b9388a118e3..2bdd7ff8f11 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/OrderEvents.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/OrderEvents.java @@ -24,6 +24,7 @@ import com.codenameone.examples.savor.domain.OrderEvent; import com.codenameone.examples.savor.repository.OrderEventRepository; import java.io.IOException; +import java.time.Instant; /// The history of an order: one row per move, with who made it. Written in /// the transaction that made the move. @@ -41,7 +42,7 @@ public void record(String orderId, OrderState state, String actor) throws IOExce event.setOrderId(orderId); event.setState(state); event.setActor(actor == null ? "" : actor); - event.setCreatedAt(System.currentTimeMillis()); + event.setCreatedAt(Instant.now()); events.insert(event); } } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Orders.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Orders.java index 6d21f69e3dd..77088e66460 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Orders.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Orders.java @@ -53,6 +53,7 @@ import com.codenameone.examples.savor.repository.RestaurantRepository; import com.codenameone.examples.savor.repository.RestaurantStaffRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -299,8 +300,8 @@ private Void store(String id, String customer, CartDto cart, Quotes.Priced charg order.setAuthorizationRef(hold); order.setPaymentStatus(Payments.CASH.equals(hold) ? Payments.PENDING : Payments.AUTHORIZED); order.setPrepMinutes(priced.restaurant.getPrepMinutes()); - order.setPlacedAt(now); - order.setUpdatedAt(now); + order.setPlacedAt(Instant.ofEpochMilli(now)); + order.setUpdatedAt(Instant.ofEpochMilli(now)); order.setReason(""); orders.insert(order); for (int iter = 0; iter < priced.lines.size(); iter++) { @@ -401,7 +402,7 @@ private Void adminEnd(String by, String id, String why, Deliveries.Change[] chan @Transactional private Void end(String id, OrderState to, String actor, String reason) throws IOException { if (orders.end(id, OrderStateMachine.sources(to), to, reason, - System.currentTimeMillis()) != 1) { + Instant.now()) != 1) { CustomerOrder now = find(id); throw new ResponseStatusException(409, "That order is " + (now == null ? "gone" : describe(now.getState()))); @@ -426,7 +427,7 @@ private Void rated(String customer, String id, int stars) throws IOException { if (OrderState.DELIVERED != order.getState()) { throw new ResponseStatusException(409, "Only a delivered order can be rated"); } - if (orders.rate(id, customer, stars, System.currentTimeMillis()) != 1) { + if (orders.rate(id, customer, stars, Instant.now()) != 1) { throw new ResponseStatusException(409, "That order is already rated"); } restaurants.addRating(order.getRestaurantId(), stars); @@ -501,7 +502,7 @@ private Void accepted(String actor, String restaurantId, String id, int prepMinu throws IOException { CustomerOrder order = kitchens(restaurantId, id); if (orders.accept(id, OrderStateMachine.sources(OrderState.ACCEPTED), - OrderState.ACCEPTED, prepMinutes, System.currentTimeMillis()) != 1) { + OrderState.ACCEPTED, prepMinutes, Instant.now()) != 1) { throw new ResponseStatusException(409, "That order is " + describe(order.getState())); } @@ -531,7 +532,7 @@ public OrderDto ready(String actor, String restaurantId, String id) throws IOExc private Void readied(String actor, String restaurantId, String id) throws IOException { CustomerOrder order = kitchens(restaurantId, id); if (orders.ready(id, OrderStateMachine.sources(OrderState.READY), OrderState.READY, - System.currentTimeMillis()) != 1) { + Instant.now()) != 1) { throw new ResponseStatusException(409, "That order is " + describe(order.getState())); } @@ -544,7 +545,7 @@ private Void readied(String actor, String restaurantId, String id) throws IOExce /// kitchen. @Scheduled(fixedDelay = 15000, initialDelay = 15000, lock = "savor-kitchen") public void sweep() throws IOException { - List late = late(System.currentTimeMillis() - answerMillis); + List late = late(Instant.now().minusMillis(answerMillis)); for (int iter = 0; iter < late.size(); iter++) { String id = late.get(iter).getId(); try { @@ -562,7 +563,7 @@ public void sweep() throws IOException { // still held, and asking to end it again is refused: it has ended. // Releasing is safe to repeat -- see Payments.release -- so this // finishes what was left, for every way an order ends short of the door. - List held = unreleased(System.currentTimeMillis() - UNRELEASED_MILLIS); + List held = unreleased(Instant.now().minusMillis(UNRELEASED_MILLIS)); for (int iter = 0; iter < held.size(); iter++) { payments.release(held.get(iter).getId()); } @@ -576,12 +577,12 @@ public void sweep() throws IOException { OrderState.CANCELLED_BY_CUSTOMER, OrderState.CANCELLED_BY_ADMIN, OrderState.NO_COURIERS}; @Transactional(readOnly = true) - private List late(long before) { + private List late(Instant before) { return orders.findByStateAndPlacedAtLessThan(OrderState.PLACED, before); } @Transactional(readOnly = true) - private List unreleased(long before) { + private List unreleased(Instant before) { return orders.unreleased(ENDED_SHORT, new String[] {Payments.AUTHORIZED, Payments.PENDING}, before, new PageRequest(0, 50)); @@ -716,8 +717,8 @@ private OrderDto toDto(CustomerOrder order, String viewer, boolean customer, boo if (OrderState.PICKED_UP == state && delivery != null && delivery.etaMinutes() > 0) { eta = delivery.etaMinutes(); } else { - long cooked = (order.getAcceptedAt() == 0L ? order.getPlacedAt() - : order.getAcceptedAt()) + order.getPrepMinutes() * 60000L; + long cooked = (order.getAcceptedAt().toEpochMilli() == 0L ? order.getPlacedAt().toEpochMilli() + : order.getAcceptedAt().toEpochMilli()) + order.getPrepMinutes() * 60000L; int left = (int) Math.max(0L, (cooked - System.currentTimeMillis()) / 60000L); eta = left + ride; } @@ -734,8 +735,9 @@ private OrderDto toDto(CustomerOrder order, String viewer, boolean customer, boo order.getDiscountCents(), order.getTipCents(), order.getTotalCents(), order.getCurrency(), order.getDropoffLat(), order.getDropoffLng(), order.getDropoffAddress(), order.getNote(), order.getMethodLabel(), - order.getPaymentStatus(), order.getPrepMinutes(), order.getPlacedAt(), - order.getAcceptedAt(), order.getReadyAt(), order.getDeliveredAt(), eta, + order.getPaymentStatus(), order.getPrepMinutes(), order.getPlacedAt().toEpochMilli(), + order.getAcceptedAt().toEpochMilli(), order.getReadyAt().toEpochMilli(), + order.getDeliveredAt().toEpochMilli(), eta, order.getReason(), order.getStars(), delivery); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Promos.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Promos.java index 5726384ae6d..43ed7cd6b3e 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Promos.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Promos.java @@ -25,6 +25,7 @@ import com.codenameone.examples.savor.api.PromoDto; import com.codenameone.examples.savor.domain.Promo; import com.codenameone.examples.savor.repository.PromoRepository; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -77,7 +78,7 @@ public PromoDto save(PromoDto form) { if (unsaved) { row = new Promo(); row.setCode(code); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); } row.setPercentOff(form.percentOff()); row.setAmountOffCents(form.amountOffCents()); diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Quotes.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Quotes.java index fd64514b7eb..d1b896bc1fd 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Quotes.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/order/Quotes.java @@ -41,6 +41,7 @@ import com.codenameone.examples.savor.repository.PromoUseRepository; import com.codenameone.examples.savor.repository.RestaurantRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -119,7 +120,7 @@ public PricingDto pricing() throws IOException { } private PricingDto toDto(Pricing row) { - if (row == null || row.getUpdatedAt() == 0L) { + if (row == null || Instant.EPOCH.equals(row.getUpdatedAt())) { return defaults; } return new PricingDto(defaults.currency(), row.getBaseCents(), row.getPerKmCents(), @@ -143,7 +144,7 @@ public PricingDto save(String by, PricingDto wanted) throws IOException { if (prices.change(PricingRepository.ONLY.intValue(), wanted.baseCents(), wanted.perKmCents(), wanted.surge(), wanted.smallOrderCents(), wanted.smallOrderFeeCents(), wanted.serviceFeePercent(), wanted.taxPercent(), - wanted.commissionPercent(), System.currentTimeMillis(), by) == 0) { + wanted.commissionPercent(), Instant.now(), by) == 0) { throw new IllegalStateException("The pricing row is missing; the V6 migration " + "creates it"); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/pay/Payments.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/pay/Payments.java index 35c5fb933c2..28479f62f9e 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/pay/Payments.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/pay/Payments.java @@ -48,6 +48,7 @@ import com.codenameone.examples.savor.repository.DeliveryRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -211,7 +212,7 @@ private String customerForSetup(String username) { /// that are neither finished nor abandoned. private void refuseTooManySetups(String username) { if (setups.countByUsernameAndCompletedFalseAndCreatedAtGreaterThan(username, - System.currentTimeMillis() - SETUP_MILLIS) >= MAX_OPEN_SETUPS) { + Instant.now().minusMillis(SETUP_MILLIS)) >= MAX_OPEN_SETUPS) { throw new ResponseStatusException(429, "Too many cards are being added. Finish one, or try again later"); } @@ -228,7 +229,7 @@ private void refuseTooManySetups(String username) { @Transactional public void sweepSetups() throws IOException { setups.deleteByCompletedTrue(); - setups.deleteByCreatedAtLessThan(System.currentTimeMillis() - 2L * SETUP_MILLIS); + setups.deleteByCreatedAtLessThan(Instant.now().minusMillis(2L * SETUP_MILLIS)); } /// Keeps the reference the processor made for a customer on first use, and @@ -276,7 +277,7 @@ private void keepSetup(String username, String id, String reference) { row.setId(id); row.setUsername(username); row.setReference(reference); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); row.setCompleted(false); setups.insert(row); } @@ -339,7 +340,7 @@ private String[] openSetup(String username, String setupId) { PaymentSetup setup = setupId == null || setupId.length() == 0 || setupId.length() > 32 ? null : setups.findFirstByIdAndUsername(setupId, username); if (setup == null || setup.isCompleted() - || setup.getCreatedAt() < System.currentTimeMillis() - SETUP_MILLIS) { + || setup.getCreatedAt().plusMillis(SETUP_MILLIS).isBefore(Instant.now())) { throw new ResponseStatusException(404, "No such card setup"); } PaymentCustomer customer = customers.findById(username); @@ -368,8 +369,9 @@ private PaymentMethodDto keepCard(String username, String setupId, String id, // Cards are listed in the order they were added, and two added in the // same millisecond would have no order: the later is stamped after // the one before it. - Long newest = cards.newestAt(username); - long after = newest == null ? 0L : newest.longValue() + 1L; + Instant newest = cards.newestAt(username); + Instant now = Instant.now(); + Instant after = newest == null ? Instant.EPOCH : newest.plusMillis(1L); PaymentMethod row = new PaymentMethod(); row.setId(id); row.setUsername(username); @@ -379,7 +381,7 @@ private PaymentMethodDto keepCard(String username, String setupId, String id, row.setExpYear(card.expYear); row.setToken(card.token); row.setPreferred(first); - row.setCreatedAt(Math.max(System.currentTimeMillis(), after)); + row.setCreatedAt(after.isAfter(now) ? after : now); cards.insert(row); return card(row); } @@ -509,8 +511,8 @@ public void forget(String username) throws IOException { } } - private static long retriedSince() { - return System.currentTimeMillis() - RETRY_MILLIS; + private static Instant retriedSince() { + return Instant.now().minusMillis(RETRY_MILLIS); } // --------------------------------------------------------------- charges @@ -591,7 +593,7 @@ private CustomerOrder order(String id) { @Transactional private void orderPaymentStatus(String id, String status) { - orders.paymentStatus(id, status, System.currentTimeMillis()); + orders.paymentStatus(id, status, Instant.now()); } /// Writes what came of a delivery's payment to the delivery and to its @@ -600,7 +602,7 @@ private void orderPaymentStatus(String id, String status) { /// caller's transaction. private void paymentStatus(String deliveryId, String status) { deliveries.paymentStatus(deliveryId, status); - orders.paymentStatus(deliveryId, status, System.currentTimeMillis()); + orders.paymentStatus(deliveryId, status, Instant.now()); } /// Settles a delivery that has just completed and returns [#PAID], [#FAILED], @@ -675,7 +677,7 @@ private void keepPayment(String deliveryId, long amount, String currency, String row.setCurrency(currency); row.setStatus(status); row.setProviderRef(reference); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); payments.insert(row); } @@ -869,7 +871,7 @@ private List refundsPending() { @Transactional private Delivery endRefund(String deliveryId, String outcome) { if (payments.endRefund(deliveryId, outcome, - REFUNDED.equals(outcome) ? System.currentTimeMillis() : 0L) != 1) { + REFUNDED.equals(outcome) ? Instant.now() : Instant.EPOCH) != 1) { return null; } paymentStatus(deliveryId, outcome); @@ -991,7 +993,7 @@ private void keepRefund(String deliveryId, PaymentProvider.Refund fare, payment.setRefundRef(cut(fare.reference, 64)); payment.setTipRefundRef(tip == null ? "" : cut(tip.reference, 64)); payment.setRefundReason(reason); - payment.setRefundedAt(pending ? 0L : System.currentTimeMillis()); + payment.setRefundedAt(pending ? Instant.EPOCH : Instant.now()); } /// Records a refund of the fare whose tip could not be refunded: the delivery @@ -1004,7 +1006,7 @@ private void keepPartialRefund(String deliveryId, PaymentProvider.Refund fare, S payment.setRefundRef(cut(fare.reference, 64)); payment.setTipRefundRef(""); payment.setRefundReason(reason); - payment.setRefundedAt(0L); + payment.setRefundedAt(Instant.EPOCH); } // -------------------------------------------------------------- receipts @@ -1041,7 +1043,7 @@ public ReceiptDto receipt(String viewer, boolean admin, String deliveryId) throw throw new ResponseStatusException(404, "No such receipt"); } Payment payment = payments.findById(deliveryId); - return receipt(delivery, payment == null ? 0L : payment.getCreatedAt(), admin, + return receipt(delivery, payment == null ? 0L : payment.getCreatedAt().toEpochMilli(), admin, new HashMap()); } @@ -1058,7 +1060,7 @@ private List receipts(List completed, boolean admin) { List rows = payments.findByDeliveryIdIn(ids); for (int iter = 0; iter < rows.size(); iter++) { Payment payment = rows.get(iter); - paidAt.put(payment.getDeliveryId(), Long.valueOf(payment.getCreatedAt())); + paidAt.put(payment.getDeliveryId(), Long.valueOf(payment.getCreatedAt().toEpochMilli())); } } Map couriers = new HashMap(); @@ -1252,7 +1254,7 @@ private PaymentMethod card(String username, String id) { /// A card tip left unknown counts too, with no time limit: see [#tip]. /// Its retry charges the delivery's card under the same key, so with the card /// gone a tip that may have been charged would be cleared as refused. - private boolean awaitsCharge(String customer, String methodId, long since) { + private boolean awaitsCharge(String customer, String methodId, Instant since) { List tipped = deliveries.findByCustomerAndPaymentStatusAndTipCentsGreaterThan(customer, PAID, 0L); for (Delivery delivery : tipped) { diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/push/OrderPushes.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/push/OrderPushes.java index 5b99403e1df..6e061e83002 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/push/OrderPushes.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/push/OrderPushes.java @@ -48,6 +48,7 @@ import com.codenameone.examples.savor.repository.RestaurantStaffRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -182,8 +183,8 @@ public void deliveryChanged(String id, DeliveryState state, String courier) { @Scheduled(fixedDelay = 60000, initialDelay = 50000, lock = "savor-activity-ends") public void endLeftBehind() throws IOException { long now = System.currentTimeMillis(); - dropEndedBefore(now - END_RETRY_MILLIS); - List left = leftBehind(now - END_GRACE_MILLIS); + dropEndedBefore(Instant.ofEpochMilli(now - END_RETRY_MILLIS)); + List left = leftBehind(Instant.ofEpochMilli(now - END_GRACE_MILLIS)); Exception failed = null; for (int iter = 0; iter < left.size(); iter++) { String id = left.get(iter).getDeliveryId(); @@ -204,13 +205,13 @@ public void endLeftBehind() throws IOException { } @Transactional - private void dropEndedBefore(long before) { - activities.dropEndedBefore(before); + private void dropEndedBefore(Instant before) { + activities.dropEndedBefore(Instant.EPOCH, before); } @Transactional(readOnly = true) - private List leftBehind(long before) { - return activities.leftBehind(before, new PageRequest(0, 50)); + private List leftBehind(Instant before) { + return activities.leftBehind(Instant.EPOCH, before, new PageRequest(0, 50)); } @Transactional @@ -280,11 +281,11 @@ public DeliveryActivityDto attach(String customer, String orderId, DeliveryActiv row.setDeliveryId(orderId); row.setUsername(customer); row.setActivityId(activityId); - row.setSentAt(System.currentTimeMillis()); + row.setSentAt(Instant.now()); activities.insert(row); } else { row.setActivityId(activityId); - row.setSentAt(System.currentTimeMillis()); + row.setSentAt(Instant.now()); } return new DeliveryActivityDto(activityId); } @@ -400,7 +401,7 @@ private List compose(String id, OrderState state) throws IOException { } // end::savor-push-messages[] if (!state.isActive() && activity != null) { - activities.markEnded(id, System.currentTimeMillis()); + activities.markEnded(id, Instant.now(), Instant.EPOCH); } if (toCustomer != null && !wants(customer, OrderState.DELIVERED == state)) { toCustomer = null; @@ -485,7 +486,7 @@ private List moved(String orderId, double lat, double lng) throws IOEx long now = System.currentTimeMillis(); // A conditional update, so that two reports arriving together send one // update between them. - if (activities.claim(orderId, now, now - activityMillis) != 1) { + if (activities.claim(orderId, Instant.ofEpochMilli(now), Instant.ofEpochMilli(now - activityMillis)) != 1) { return out; } CustomerOrder order = orders.findById(orderId); diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/push/PushDevices.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/push/PushDevices.java index 30e63516f9a..cb4a9db6d83 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/push/PushDevices.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/push/PushDevices.java @@ -30,6 +30,7 @@ import com.codenameone.examples.savor.repository.PushDeviceRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -112,7 +113,7 @@ private void makeRoom(String username) { while (held.size() >= MAX_PER_ACCOUNT) { PushDevice oldest = held.get(0); for (PushDevice each : held) { - if (each.getUpdatedAt() < oldest.getUpdatedAt()) { + if (each.getUpdatedAt().isBefore(oldest.getUpdatedAt())) { oldest = each; } } @@ -151,7 +152,7 @@ List targetsOf(String username) { private static void fill(PushDevice row, String username, PushDeviceDto device, long now) { row.setUsername(username); row.setPlatform(Text.optional(device.platform(), 32, "the platform")); - row.setUpdatedAt(now); + row.setUpdatedAt(Instant.ofEpochMilli(now)); } /// The device as a target of the push service, which also spells its diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CourierApplicationRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CourierApplicationRepository.java index 0a71b192ff4..78091c4b52b 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CourierApplicationRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CourierApplicationRepository.java @@ -26,6 +26,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.savor.domain.CourierApplication; +import java.time.Instant; import java.util.List; /// Applications to deliver, one per account at most, keyed by the account. @@ -72,7 +73,7 @@ public interface CourierApplicationRepository extends CrudRepository :to") int approveUnlessApproved(@Param("username") String username, - @Param("to") String approved, @Param("at") long at, @Param("by") String by); + @Param("to") String approved, @Param("at") Instant at, @Param("by") String by); /// Hands an application in: from the status it was read in to `to`, with /// the last rejection's reason cleared. @@ -89,7 +90,7 @@ int approveUnlessApproved(@Param("username") String username, @Query("update CourierApplication a set a.status = :to, a.submittedAt = :at, " + "a.rejectionReason = '' where a.username = :username and a.status = :from") int submit(@Param("username") String username, @Param("from") String from, - @Param("to") String to, @Param("at") long at); + @Param("to") String to, @Param("at") Instant at); /// Makes the rest of the transaction wait its turn behind any other that /// holds, or moves, the same application. diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CourierDocumentRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CourierDocumentRepository.java index cf4fe3015a6..5148ee9b4b7 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CourierDocumentRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CourierDocumentRepository.java @@ -26,6 +26,7 @@ import com.codename1.orm.session.Identifier; import com.codenameone.examples.savor.domain.CourierDocument; +import java.time.Instant; import java.util.List; /// The documents of applications to deliver, keyed by @@ -58,7 +59,7 @@ public interface CourierDocumentRepository extends CrudRepository freeInBox(@Param("fresh") long fresh, @Param("south") double south, + List freeInBox(@Param("fresh") Instant fresh, @Param("south") double south, @Param("north") double north, @Param("west") double west, @Param("east") double east, @Param("approved") String approved, @Param("withDelivery") DeliveryState[] withDelivery); @@ -85,7 +86,7 @@ List freeInBox(@Param("fresh") long fresh, @Param("south") double int takeOffLine(@Param("username") String username); /// The couriers on line who reported in at or after `seenSince`. - long countByOnlineTrueAndLastSeenGreaterThanEqual(long seenSince); + long countByOnlineTrueAndLastSeenGreaterThanEqual(Instant seenSince); int deleteByUsername(String username); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CustomerOrderRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CustomerOrderRepository.java index 43ab2087711..e73d898ab97 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CustomerOrderRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/CustomerOrderRepository.java @@ -27,6 +27,7 @@ import com.codenameone.examples.savor.api.OrderState; import com.codenameone.examples.savor.domain.CustomerOrder; +import java.time.Instant; import java.util.List; /// Every order. @@ -44,16 +45,16 @@ List findTop50ByRestaurantIdAndStateInOrderByPlacedAtDesc(String OrderState[] states); List findByRestaurantIdAndStateAndDeliveredAtGreaterThanEqual(String restaurantId, - OrderState state, long since); + OrderState state, Instant since); - List findByStateAndPlacedAtLessThan(OrderState state, long before); + List findByStateAndPlacedAtLessThan(OrderState state, Instant before); - List findByStateAndAcceptedAtLessThan(OrderState state, long before); + List findByStateAndAcceptedAtLessThan(OrderState state, Instant before); boolean existsByCustomerAndMethodIdAndStateIn(String customer, String methodId, OrderState[] states); - List findByPaymentStatusAndUpdatedAtLessThan(String paymentStatus, long before); + List findByPaymentStatusAndUpdatedAtLessThan(String paymentStatus, Instant before); /// Orders in one of `states` whose payment is one of `statuses` and has /// not changed since `before`, oldest first: ended orders whose hold was @@ -62,12 +63,12 @@ boolean existsByCustomerAndMethodIdAndStateIn(String customer, String methodId, + "and o.paymentStatus in :statuses and o.updatedAt < :before " + "order by o.updatedAt asc") List unreleased(@Param("states") OrderState[] states, - @Param("statuses") String[] statuses, @Param("before") long before, PageRequest page); + @Param("statuses") String[] statuses, @Param("before") Instant before, PageRequest page); @Query("select o from CustomerOrder o order by o.placedAt desc") List newest(PageRequest page); - List findByPlacedAtGreaterThanEqual(long since); + List findByPlacedAtGreaterThanEqual(Instant since); long countByCustomerAndStateIn(String customer, OrderState[] states); @@ -78,54 +79,54 @@ List unreleased(@Param("states") OrderState[] states, @Query("update CustomerOrder o set o.state = :to, o.updatedAt = :now " + "where o.id = :id and o.state in :from") int move(@Param("id") String id, @Param("from") OrderState[] from, @Param("to") OrderState to, - @Param("now") long now); + @Param("now") Instant now); @Modifying(clearAutomatically = true) @Query("update CustomerOrder o set o.paymentStatus = :status, o.updatedAt = :now " + "where o.id = :id") - int paymentStatus(@Param("id") String id, @Param("status") String status, @Param("now") long now); + int paymentStatus(@Param("id") String id, @Param("status") String status, @Param("now") Instant now); /// The kitchen takes an order and says how long it needs. @Modifying(clearAutomatically = true) @Query("update CustomerOrder o set o.state = :to, o.updatedAt = :now, o.acceptedAt = :now, " + "o.prepMinutes = :prep where o.id = :id and o.state in :from") int accept(@Param("id") String id, @Param("from") OrderState[] from, - @Param("to") OrderState to, @Param("prep") int prep, @Param("now") long now); + @Param("to") OrderState to, @Param("prep") int prep, @Param("now") Instant now); /// The kitchen has finished an order. @Modifying(clearAutomatically = true) @Query("update CustomerOrder o set o.state = :to, o.updatedAt = :now, o.readyAt = :now " + "where o.id = :id and o.state in :from") int ready(@Param("id") String id, @Param("from") OrderState[] from, - @Param("to") OrderState to, @Param("now") long now); + @Param("to") OrderState to, @Param("now") Instant now); /// The order reached the door. @Modifying(clearAutomatically = true) @Query("update CustomerOrder o set o.state = :to, o.updatedAt = :now, o.deliveredAt = :now " + "where o.id = :id and o.state in :from") int deliver(@Param("id") String id, @Param("from") OrderState[] from, - @Param("to") OrderState to, @Param("now") long now); + @Param("to") OrderState to, @Param("now") Instant now); /// An order ends without reaching the door, and why. @Modifying(clearAutomatically = true) @Query("update CustomerOrder o set o.state = :to, o.updatedAt = :now, o.reason = :reason " + "where o.id = :id and o.state in :from") int end(@Param("id") String id, @Param("from") OrderState[] from, - @Param("to") OrderState to, @Param("reason") String reason, @Param("now") long now); + @Param("to") OrderState to, @Param("reason") String reason, @Param("now") Instant now); /// A customer's stars for a delivered order, once. @Modifying(clearAutomatically = true) @Query("update CustomerOrder o set o.stars = :stars, o.updatedAt = :now " + "where o.id = :id and o.customer = :customer and o.stars = 0") int rate(@Param("id") String id, @Param("customer") String customer, - @Param("stars") int stars, @Param("now") long now); + @Param("stars") int stars, @Param("now") Instant now); /// The orders placed since `since`, counted by restaurant: `{id, count}`. @Query("select o.restaurantId, count(o) from CustomerOrder o where o.placedAt >= :since " + "group by o.restaurantId") - List countByRestaurant(@Param("since") long since); + List countByRestaurant(@Param("since") Instant since); - long countByPlacedAtGreaterThanEqual(long since); + long countByPlacedAtGreaterThanEqual(Instant since); long countByStateIn(OrderState[] states); @@ -137,7 +138,7 @@ int rate(@Param("id") String id, @Param("customer") String customer, /// The orders placed since `since`, counted by state: `{state, count}`. @Query("select o.state, count(o) from CustomerOrder o where o.placedAt >= :since " + "group by o.state") - List countByState(@Param("since") long since); + List countByState(@Param("since") Instant since); /// One row for each order placed since `since`: `{id, placedAt, state, /// totalCents, paymentStatus, deliveredAt}`. @@ -149,7 +150,7 @@ int rate(@Param("id") String id, @Param("customer") String customer, /// see the two as one expression. @Query("select o.id, o.placedAt, o.state, o.totalCents, o.paymentStatus, o.deliveredAt " + "from CustomerOrder o where o.placedAt >= :since") - List timeline(@Param("since") long since); + List timeline(@Param("since") Instant since); /// Locks the order's row until the transaction ends, if it is still the /// customer's and in one of `states`; 1 when it is, 0 when it is not. diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryActivityRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryActivityRepository.java index c4e42751c00..982a0364719 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryActivityRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryActivityRepository.java @@ -26,6 +26,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.savor.domain.DeliveryActivity; +import java.time.Instant; import java.util.List; /// The Live Activities customers follow their deliveries in, by delivery. @@ -40,23 +41,27 @@ public interface DeliveryActivityRepository extends CrudRepository 0 and a.endedAt < :before " + @Query("select a from DeliveryActivity a where a.endedAt > :never and a.endedAt < :before " + "order by a.endedAt") - List leftBehind(@Param("before") long before, PageRequest page); + List leftBehind(@Param("never") Instant never, @Param("before") Instant before, + PageRequest page); /// Forgets the activities whose delivery ended before `before`. @Modifying - @Query("delete from DeliveryActivity a where a.endedAt > 0 and a.endedAt < :before") - int dropEndedBefore(@Param("before") long before); + @Query("delete from DeliveryActivity a where a.endedAt > :never and a.endedAt < :before") + int dropEndedBefore(@Param("never") Instant never, @Param("before") Instant before); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryEventRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryEventRepository.java index 30c49dfc92e..0e30b71449f 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryEventRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryEventRepository.java @@ -25,6 +25,7 @@ import com.codenameone.examples.savor.api.DeliveryState; import com.codenameone.examples.savor.domain.DeliveryEvent; +import java.time.Instant; import java.util.List; /// What happened to each delivery: one row for every state it came into. @@ -42,5 +43,5 @@ public interface DeliveryEventRepository extends CrudRepository= :since)") - List reached(@Param("since") long since, @Param("state") DeliveryState state); + List reached(@Param("since") Instant since, @Param("state") DeliveryState state); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryRepository.java index ddb775291aa..2512f7c304c 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/DeliveryRepository.java @@ -27,6 +27,7 @@ import com.codenameone.examples.savor.api.DeliveryState; import com.codenameone.examples.savor.domain.Delivery; +import java.time.Instant; import java.util.List; /// Deliveries. @@ -70,11 +71,11 @@ boolean existsByCustomerAndMethodIdAndStateIn(String customer, String methodId, /// `paymentStatus` and which ended after `since`, is to be charged to /// this method. boolean existsByCustomerAndStateAndPaymentStatusAndUpdatedAtGreaterThanAndMethodId( - String customer, DeliveryState state, String paymentStatus, long since, String methodId); + String customer, DeliveryState state, String paymentStatus, Instant since, String methodId); /// The same, to be charged to any method but `methodId`. boolean existsByCustomerAndStateAndPaymentStatusAndUpdatedAtGreaterThanAndMethodIdNot( - String customer, DeliveryState state, String paymentStatus, long since, String methodId); + String customer, DeliveryState state, String paymentStatus, Instant since, String methodId); /// A customer's deliveries whose payment is `paymentStatus` and that carry a tip. List findByCustomerAndPaymentStatusAndTipCentsGreaterThan(String customer, @@ -99,16 +100,16 @@ List findByCustomerAndStateOrderByRequestedAtDesc(String customer, Del List newest(PageRequest page); /// The deliveries in `state` whose offer ran out before `now`. - List findByStateAndOfferExpiresAtLessThan(DeliveryState state, long now); + List findByStateAndOfferExpiresAtLessThan(DeliveryState state, Instant now); /// The deliveries in `state`, the one that has waited longest first. List findByStateOrderByRequestedAtAsc(DeliveryState state); /// A courier's deliveries in `state` that changed at or after a time. List findByCourierAndStateAndUpdatedAtGreaterThanEqual(String courier, - DeliveryState state, long since); + DeliveryState state, Instant since); - long countByRequestedAtGreaterThanEqual(long since); + long countByRequestedAtGreaterThanEqual(Instant since); long countByStateIn(DeliveryState[] states); @@ -126,14 +127,14 @@ long countByCustomerAndStateOrCourierAndState(String customer, DeliveryState asC @Query("update Delivery r set r.state = :to, r.updatedAt = :now " + "where r.id = :id and r.state in :from and r.customer = :customer") int moveAsCustomer(@Param("id") String id, @Param("from") DeliveryState[] from, - @Param("to") DeliveryState to, @Param("now") long now, @Param("customer") String customer); + @Param("to") DeliveryState to, @Param("now") Instant now, @Param("customer") String customer); /// Moves a delivery of `courier`'s from one of `from` to `to`. @Modifying(clearAutomatically = true) @Query("update Delivery r set r.state = :to, r.updatedAt = :now " + "where r.id = :id and r.state in :from and r.courier = :courier") int moveAsCourier(@Param("id") String id, @Param("from") DeliveryState[] from, - @Param("to") DeliveryState to, @Param("now") long now, @Param("courier") String courier); + @Param("to") DeliveryState to, @Param("now") Instant now, @Param("courier") String courier); // tag::savor-delivery-move[] /// Takes an offer made to `courier`: refused once the offer has lapsed, as @@ -143,7 +144,7 @@ int moveAsCourier(@Param("id") String id, @Param("from") DeliveryState[] from, + "where r.id = :id and r.state in :from and r.courier = :courier " + "and r.offerExpiresAt >= :now") int takeOffer(@Param("id") String id, @Param("from") DeliveryState[] from, - @Param("to") DeliveryState to, @Param("now") long now, @Param("courier") String courier); + @Param("to") DeliveryState to, @Param("now") Instant now, @Param("courier") String courier); // end::savor-delivery-move[] /// Gives a delivery of `courier`'s back to be offered again, writing @@ -152,7 +153,7 @@ int takeOffer(@Param("id") String id, @Param("from") DeliveryState[] from, @Query("update Delivery r set r.state = :to, r.updatedAt = :now, r.courier = :newCourier " + "where r.id = :id and r.state in :from and r.courier = :courier") int giveBack(@Param("id") String id, @Param("from") DeliveryState[] from, - @Param("to") DeliveryState to, @Param("now") long now, @Param("courier") String courier, + @Param("to") DeliveryState to, @Param("now") Instant now, @Param("courier") String courier, @Param("newCourier") String newCourier); /// Holds `customer`'s delivery while it is in one of `states`, answering 0 when @@ -172,15 +173,15 @@ int holdWhile(@Param("id") String id, @Param("customer") String customer, @Query("update Delivery r set r.state = :to, r.updatedAt = :now " + "where r.id = :id and r.state in :from") int moveByServer(@Param("id") String id, @Param("from") DeliveryState[] from, - @Param("to") DeliveryState to, @Param("now") long now); + @Param("to") DeliveryState to, @Param("now") Instant now); /// Offers a delivery to `courier` until `expiresAt`. @Modifying(clearAutomatically = true) @Query("update Delivery r set r.state = :to, r.updatedAt = :now, r.courier = :courier, " + "r.offerExpiresAt = :expiresAt where r.id = :id and r.state in :from") int offer(@Param("id") String id, @Param("from") DeliveryState[] from, - @Param("to") DeliveryState to, @Param("now") long now, @Param("courier") String courier, - @Param("expiresAt") long expiresAt); + @Param("to") DeliveryState to, @Param("now") Instant now, @Param("courier") String courier, + @Param("expiresAt") Instant expiresAt); // ----------------------------------------------------------- the rest @@ -201,7 +202,7 @@ int offer(@Param("id") String id, @Param("from") DeliveryState[] from, @Query("select r from Delivery r where r.state = 'COMPLETED' " + "and (r.paymentStatus = 'PENDING' or r.paymentStatus = 'AUTHORIZED') " + "and r.updatedAt < :before and r.updatedAt > :after order by r.updatedAt asc") - List unsettled(@Param("after") long after, @Param("before") long before, + List unsettled(@Param("after") Instant after, @Param("before") Instant before, PageRequest page); /// Records how the charge for a delivery came out. A statement of its own and @@ -263,13 +264,13 @@ List unsettled(@Param("after") long after, @Param("before") long befor @Query("select count(r), coalesce(sum(r.courierCents), 0) from Delivery r " + "where r.courier = :courier and r.state = 'COMPLETED' and r.paymentStatus = 'PAID' " + "and r.updatedAt >= :since") - Object[] paidTotalsSince(@Param("courier") String courier, @Param("since") long since); + Object[] paidTotalsSince(@Param("courier") String courier, @Param("since") Instant since); /// What the courier's share of their completed, paid deliveries came to since /// a time. @Query("select coalesce(sum(r.courierCents), 0) from Delivery r where r.courier = :courier " + "and r.state = 'COMPLETED' and r.paymentStatus = 'PAID' and r.updatedAt >= :since") - Long paidSince(@Param("courier") String courier, @Param("since") long since); + Long paidSince(@Param("courier") String courier, @Param("since") Instant since); /// The courier's share of the fares of every delivery they completed and that /// was paid for -- in cash, or by a card whose charge came back. A charge @@ -302,7 +303,7 @@ List unsettled(@Param("after") long after, @Param("before") long befor @Query("select r.id from Delivery r where r.courier = :courier and r.state = 'COMPLETED' " + "and r.updatedAt >= :since and r.methodId <> 'cash' and r.paymentStatus = 'PAID' " + "and r.id in (select p.deliveryId from Payment p where p.tipRef <> '')") - List tipChargedSince(@Param("courier") String courier, @Param("since") long since); + List tipChargedSince(@Param("courier") String courier, @Param("since") Instant since); /// What customers paid in fares for deliveries in `state` whose payment is `paid`. @Query("select coalesce(sum(r.fareCents), 0) from Delivery r " @@ -312,17 +313,17 @@ List unsettled(@Param("after") long after, @Param("before") long befor /// The fares of the deliveries in `state` asked for since `since`, paid or not. @Query("select coalesce(sum(r.fareCents), 0) from Delivery r " + "where r.requestedAt >= :since and r.state = :state") - Long faresSince(@Param("since") long since, @Param("state") DeliveryState state); + Long faresSince(@Param("since") Instant since, @Param("state") DeliveryState state); /// The deliveries asked for since `since`, counted by state: `{state, count}`. @Query("select r.state, count(r) from Delivery r where r.requestedAt >= :since group by r.state") - List countByState(@Param("since") long since); + List countByState(@Param("since") Instant since); /// The deliveries in `state` asked for since `since`, counted by courier: /// `{courier, count}`. @Query("select r.courier, count(r) from Delivery r where r.requestedAt >= :since " + "and r.state = :state group by r.courier") - List countByCourier(@Param("since") long since, @Param("state") DeliveryState state); + List countByCourier(@Param("since") Instant since, @Param("state") DeliveryState state); /// One row for each delivery asked for since `since`: `{id, requestedAt, /// state, fareCents, paymentStatus}`. @@ -335,7 +336,7 @@ List unsettled(@Param("after") long after, @Param("before") long befor /// word does not see those as one expression. @Query("select r.id, r.requestedAt, r.state, r.fareCents, r.paymentStatus from Delivery r " + "where r.requestedAt >= :since") - List timeline(@Param("since") long since); + List timeline(@Param("since") Instant since); /// What a customer paid for deliveries in `state` whose payment is `paid`: /// `{fares, fees, tips}`. diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/LiveTicketRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/LiveTicketRepository.java index 28eda4163e2..88d51bbd62f 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/LiveTicketRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/LiveTicketRepository.java @@ -21,6 +21,7 @@ import com.codename1.orm.repository.CrudRepository; import com.codename1.orm.repository.Repository; import com.codenameone.examples.savor.domain.LiveTicket; +import java.time.Instant; /// The tickets that open a live connection. Only the hash of a ticket is /// stored, and it is the row's key. @@ -33,7 +34,7 @@ public interface LiveTicketRepository extends CrudRepository int deleteByTicketHash(String ticketHash); /// Deletes the tickets that went stale before `now`. - int deleteByExpiresAtLessThan(long now); + int deleteByExpiresAtLessThan(Instant now); int deleteByUsername(String username); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/ModerationEventRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/ModerationEventRepository.java index c26c87168d8..2b7d5db2ee7 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/ModerationEventRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/ModerationEventRepository.java @@ -24,6 +24,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.savor.domain.ModerationEvent; +import java.time.Instant; import java.util.List; /// The record of what the admins did to each account. @@ -32,7 +33,7 @@ public interface ModerationEventRepository extends CrudRepository findTop100ByUsernameOrderByCreatedAtDescIdAsc(String username); diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/PaymentMethodRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/PaymentMethodRepository.java index 38dd2ce9c24..6f7c4e4a202 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/PaymentMethodRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/PaymentMethodRepository.java @@ -24,6 +24,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.savor.domain.PaymentMethod; +import java.time.Instant; import java.util.List; /// The cards accounts saved. @@ -42,7 +43,7 @@ public interface PaymentMethodRepository extends CrudRepository { @Query("update Payment p set p.status = :status, p.refundedAt = :at " + "where p.deliveryId = :id and p.status = 'REFUND_PENDING'") int endRefund(@Param("id") String deliveryId, @Param("status") String status, - @Param("at") long at); + @Param("at") Instant at); } diff --git a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/PaymentSetupRepository.java b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/PaymentSetupRepository.java index 9f6aa508e46..e0bbc2b43e8 100644 --- a/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/PaymentSetupRepository.java +++ b/scripts/savor/backend/src/main/java/com/codenameone/examples/savor/repository/PaymentSetupRepository.java @@ -24,6 +24,7 @@ import com.codename1.orm.repository.Query; import com.codename1.orm.repository.Repository; import com.codenameone.examples.savor.domain.PaymentSetup; +import java.time.Instant; /// The card setups accounts began with the payment processor. @Repository(entity = PaymentSetup.class, key = String.class) @@ -39,7 +40,7 @@ public interface PaymentSetupRepository extends CrudRepository { /// When each account made since `since` was made. @Query("select p.createdAt from Profile p where p.createdAt >= :since") - List signUps(@Param("since") long since); + List signUps(@Param("since") Instant since); } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/account/Accounts.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/account/Accounts.java index 821c571194d..060dbda2b2b 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/account/Accounts.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/account/Accounts.java @@ -36,6 +36,7 @@ import com.codenameone.examples.skirmish.rules.Deck; import com.codenameone.examples.skirmish.shop.Catalog; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -91,8 +92,8 @@ public void create(String username, String password, String name, boolean admin) p.setDeck(Lists.join(Deck.starter())); p.setOwned(Catalog.DEFAULT_ARENA + "," + Catalog.DEFAULT_EMOTES); p.setArena(Catalog.DEFAULT_ARENA); - p.setCreatedAt(Clock.now()); - p.setLastSeen(Clock.now()); + p.setCreatedAt(Instant.now()); + p.setLastSeen(Instant.now()); profiles.insert(p); } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/AdminEndpoint.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/AdminEndpoint.java index 61124b57830..16e016b7819 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/AdminEndpoint.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/AdminEndpoint.java @@ -55,6 +55,7 @@ import com.codenameone.examples.skirmish.social.Insights; import com.codenameone.examples.skirmish.social.Pipelines; import com.codenameone.examples.skirmish.social.Promotion; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -96,7 +97,7 @@ public AdminEndpoint(Accounts accounts, ProfileRepository profiles, MatchRecordR @Override @Transactional(readOnly = true) public AdminStatsDto stats() throws Exception { - long today = Clock.dayOf(Clock.now()); + Instant today = Instant.ofEpochMilli(Clock.dayOf(Clock.now())); int gems = 0; List sold = purchases.since(today); for (StorePurchase s : sold) { @@ -104,7 +105,7 @@ public AdminStatsDto stats() throws Exception { } return new AdminStatsDto((int) profiles.count(), rooms.online(), rooms.live().size(), (int) matches.countByEndedAtGreaterThan(today), (int) flags.pendingCount(), - (int) count(profiles.suspended(Clock.now())), sold.size(), gems); + (int) count(profiles.suspended(Instant.now())), sold.size(), gems); } @Override diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/Flags.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/Flags.java index b6778461f35..dc848a877d7 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/Flags.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/Flags.java @@ -35,6 +35,7 @@ import com.codenameone.examples.skirmish.repository.MatchRecordRepository; import com.codenameone.examples.skirmish.repository.ProfileRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -115,7 +116,7 @@ Flag store(String username, String kind, String reason, String matchId, String r f.setReason(reason); f.setMatchId(matchId); f.setReporter(reporter); - f.setCreatedAt(Clock.now()); + f.setCreatedAt(Instant.now()); f.setPending(true); flags.insert(f); Profile p = profiles.findById(username); @@ -168,7 +169,7 @@ public long pendingCount() { static FlagDto toDto(Flag f, Profile p) { return new FlagDto(f.getId(), f.getUsername(), p == null ? f.getUsername() : p.getDisplayName(), - f.getKind(), f.getReason(), f.getMatchId(), f.getReporter(), f.getCreatedAt(), f.isPending()); + f.getKind(), f.getReason(), f.getMatchId(), f.getReporter(), f.getCreatedAt().toEpochMilli(), f.isPending()); } } // end::skirmish-flags[] diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/Moderation.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/Moderation.java index 418a5f3a1c6..265d12a3b46 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/Moderation.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/admin/Moderation.java @@ -37,6 +37,7 @@ import com.codenameone.examples.skirmish.repository.ProfileRepository; import com.codenameone.examples.skirmish.shop.Catalog; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -101,7 +102,7 @@ boolean apply(String admin, String username, String action, String reason, int d if (days < 1 || days > 365) { throw new ResponseStatusException(400, "Suspend for 1 to 365 days"); } - p.setSuspendedUntil(Clock.now() + days * Clock.DAY); + p.setSuspendedUntil(Instant.now().plusMillis(days * Clock.DAY)); accounts.setEnabled(username, false); closes = true; } else if (BAN.equals(action)) { @@ -110,7 +111,7 @@ boolean apply(String admin, String username, String action, String reason, int d closes = true; } else if (UNBAN.equals(action)) { p.setBanned(false); - p.setSuspendedUntil(0); + p.setSuspendedUntil(Instant.EPOCH); accounts.setEnabled(username, true); } else if (RESET_TROPHIES.equals(action)) { p.setTrophies(0); @@ -125,7 +126,7 @@ boolean apply(String admin, String username, String action, String reason, int d a.setUsername(username); a.setAction(SUSPEND.equals(action) ? SUSPEND + " " + days + "d" : action); a.setReason(reason); - a.setCreatedAt(Clock.now()); + a.setCreatedAt(Instant.now()); audit.insert(a); return closes; } @@ -140,8 +141,9 @@ public void liftExpired() { public int lift(long now) { int lifted = 0; for (Profile p : profiles.findAll()) { - if (!p.isBanned() && p.getSuspendedUntil() > 0 && p.getSuspendedUntil() <= now) { - p.setSuspendedUntil(0); + if (!p.isBanned() && p.getSuspendedUntil().isAfter(Instant.EPOCH) + && p.getSuspendedUntil().toEpochMilli() <= now) { + p.setSuspendedUntil(Instant.EPOCH); profiles.save(p); accounts.setEnabled(p.getUsername(), true); lifted++; @@ -164,7 +166,7 @@ private static List toDtos(List rows) { List out = new ArrayList(); for (AdminAction a : rows) { out.add(new AuditDto(a.getId(), a.getAdmin(), a.getUsername(), a.getAction(), a.getReason(), - a.getCreatedAt())); + a.getCreatedAt().toEpochMilli())); } return out; } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/AdminAction.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/AdminAction.java index 3d371e9559a..253ca75d0b7 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/AdminAction.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/AdminAction.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One entry of the admin audit log. Rows are only ever inserted. @Entity @@ -42,7 +43,7 @@ public class AdminAction { private String reason = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public AdminAction() { } @@ -87,11 +88,11 @@ public void setReason(String reason) { this.reason = reason; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Broadcast.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Broadcast.java index 0530c15a4b4..a149cda2e3a 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Broadcast.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Broadcast.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A push an operator sent to a segment of players, kept as the record of it. @Entity @@ -54,7 +55,7 @@ public class Broadcast { private String sentBy = ""; @Column(nullable = false) - private long sentAt; + private Instant sentAt = Instant.EPOCH; public Broadcast() { } @@ -131,11 +132,11 @@ public void setSentBy(String sentBy) { this.sentBy = sentBy; } - public long getSentAt() { + public Instant getSentAt() { return sentAt; } - public void setSentAt(long sentAt) { + public void setSentAt(Instant sentAt) { this.sentAt = sentAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Flag.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Flag.java index 34d8b6d41f2..10f3e3976d3 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Flag.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Flag.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A reason for an admin to look at a player: an opponent's report or something the server detected. @Entity @@ -45,7 +46,7 @@ public class Flag { private String reporter = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) private boolean pending; @@ -104,11 +105,11 @@ public void setReporter(String reporter) { this.reporter = reporter; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgeAsset.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgeAsset.java index f5e11a9f632..42d97421f1c 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgeAsset.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgeAsset.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An uploaded model or image, stored once under the SHA-256 of its bytes. @Entity @@ -51,7 +52,7 @@ public class ForgeAsset { private String data = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public ForgeAsset() { } @@ -120,11 +121,11 @@ public void setData(String data) { this.data = data; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgePack.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgePack.java index e2c1f8ab013..9d823f23415 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgePack.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgePack.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A pack in the Forge: its owner's draft and, once published, which version is /// current. The versions themselves are [ForgePackVersion] rows. @@ -82,10 +83,10 @@ public class ForgePack { private boolean pendingAssets; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; public ForgePack() { } @@ -234,19 +235,19 @@ public void setPendingAssets(boolean pendingAssets) { this.pendingAssets = pendingAssets; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgePackVersion.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgePackVersion.java index c88fca804af..cc7b5a2f3a0 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgePackVersion.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ForgePackVersion.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One published version of a pack, kept for good: replays and mission results /// name the version they were played on. @@ -43,7 +44,7 @@ public class ForgePackVersion { private String content = ""; @Column(nullable = false) - private long publishedAt; + private Instant publishedAt = Instant.EPOCH; public ForgePackVersion() { } @@ -88,11 +89,11 @@ public void setContent(String content) { this.content = content; } - public long getPublishedAt() { + public Instant getPublishedAt() { return publishedAt; } - public void setPublishedAt(long publishedAt) { + public void setPublishedAt(Instant publishedAt) { this.publishedAt = publishedAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/GameTicket.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/GameTicket.java index 3155f92e400..4d6779bc905 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/GameTicket.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/GameTicket.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A ticket for one connection to the live channel, as its hash. @Entity @@ -33,7 +34,7 @@ public class GameTicket { private String username = ""; @Column(nullable = false) - private long expiresAt; + private Instant expiresAt = Instant.EPOCH; public GameTicket() { } @@ -54,11 +55,11 @@ public void setUsername(String username) { this.username = username; } - public long getExpiresAt() { + public Instant getExpiresAt() { return expiresAt; } - public void setExpiresAt(long expiresAt) { + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/MatchRecord.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/MatchRecord.java index 977ff589d67..70077982f07 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/MatchRecord.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/MatchRecord.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A finished match: who played, how it ended, and the replay that reproduces it. @Entity @@ -60,7 +61,7 @@ public class MatchRecord { private int ticks; @Column(nullable = false) - private long endedAt; + private Instant endedAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(16)") private String rulesVersion = ""; @@ -159,11 +160,11 @@ public void setTicks(int ticks) { this.ticks = ticks; } - public long getEndedAt() { + public Instant getEndedAt() { return endedAt; } - public void setEndedAt(long endedAt) { + public void setEndedAt(Instant endedAt) { this.endedAt = endedAt; } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/MissionStars.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/MissionStars.java index 51d64019762..c72add2c1b9 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/MissionStars.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/MissionStars.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A player's best on one mission, and how many of those stars were paid for. @Entity @@ -48,7 +49,7 @@ public class MissionStars { private int plays; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; public MissionStars() { } @@ -109,11 +110,11 @@ public void setPlays(int plays) { this.plays = plays; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Pipeline.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Pipeline.java index 7eeb8b2d099..2eaeee1e657 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Pipeline.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Pipeline.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An engagement pipeline: a query over the players and what to do for each /// one who matches. See `social.Pipelines`. @@ -61,7 +62,7 @@ public class Pipeline { private int reached; @Column(nullable = false) - private long lastRun; + private Instant lastRun = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(190)") private String createdBy = ""; @@ -154,11 +155,11 @@ public void setReached(int reached) { this.reached = reached; } - public long getLastRun() { + public Instant getLastRun() { return lastRun; } - public void setLastRun(long lastRun) { + public void setLastRun(Instant lastRun) { this.lastRun = lastRun; } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/PipelineHit.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/PipelineHit.java index 730947c1b30..825e22a5d20 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/PipelineHit.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/PipelineHit.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// When a pipeline last acted on a player, so it waits its cool-down before /// acting on them again. The id is the pipeline id, a colon and the username. @@ -37,7 +38,7 @@ public class PipelineHit { private String username = ""; @Column(nullable = false) - private long hitAt; + private Instant hitAt = Instant.EPOCH; public String getId() { return id; @@ -63,11 +64,11 @@ public void setUsername(String username) { this.username = username; } - public long getHitAt() { + public Instant getHitAt() { return hitAt; } - public void setHitAt(long hitAt) { + public void setHitAt(Instant hitAt) { this.hitAt = hitAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Profile.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Profile.java index 91b48bbf849..ce8ca0d36d9 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Profile.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Profile.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A player's account data beyond the sign-in record: rating, currencies, deck, cosmetics and moderation state. @Entity @@ -66,16 +67,16 @@ public class Profile { private boolean muted; @Column(nullable = false) - private long suspendedUntil; + private Instant suspendedUntil = Instant.EPOCH; @Column(nullable = false) private boolean banned; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) - private long lastSeen; + private Instant lastSeen = Instant.EPOCH; @Column(nullable = false) private long adDay; @@ -193,11 +194,11 @@ public void setMuted(boolean muted) { this.muted = muted; } - public long getSuspendedUntil() { + public Instant getSuspendedUntil() { return suspendedUntil; } - public void setSuspendedUntil(long suspendedUntil) { + public void setSuspendedUntil(Instant suspendedUntil) { this.suspendedUntil = suspendedUntil; } @@ -209,19 +210,19 @@ public void setBanned(boolean banned) { this.banned = banned; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public long getLastSeen() { + public Instant getLastSeen() { return lastSeen; } - public void setLastSeen(long lastSeen) { + public void setLastSeen(Instant lastSeen) { this.lastSeen = lastSeen; } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/PushDevice.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/PushDevice.java index f61eafee87d..0626603248f 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/PushDevice.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/PushDevice.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A device an account is sent push notifications on. /// @@ -46,7 +47,7 @@ public class PushDevice { private String platform = ""; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; public PushDevice() { } @@ -91,11 +92,11 @@ public void setPlatform(String platform) { this.platform = platform; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Referral.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Referral.java index da3343c91a8..916de9aea08 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Referral.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Referral.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A player who joined through someone's invite, keyed by that player: one /// inviter each, for good. @@ -52,10 +53,10 @@ public class Referral { private boolean rewarded; @Column(nullable = false) - private long joinedAt; + private Instant joinedAt = Instant.EPOCH; @Column(nullable = false) - private long playedAt; + private Instant playedAt = Instant.EPOCH; public Referral() { } @@ -124,19 +125,19 @@ public void setRewarded(boolean rewarded) { this.rewarded = rewarded; } - public long getJoinedAt() { + public Instant getJoinedAt() { return joinedAt; } - public void setJoinedAt(long joinedAt) { + public void setJoinedAt(Instant joinedAt) { this.joinedAt = joinedAt; } - public long getPlayedAt() { + public Instant getPlayedAt() { return playedAt; } - public void setPlayedAt(long playedAt) { + public void setPlayedAt(Instant playedAt) { this.playedAt = playedAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ReferralCode.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ReferralCode.java index 52e674981e2..55faaeae845 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ReferralCode.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/ReferralCode.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A player's invite code: what their links carry, so the server knows whose friend /// has joined. @@ -34,7 +35,7 @@ public class ReferralCode { private String username = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public ReferralCode() { } @@ -55,11 +56,11 @@ public void setUsername(String username) { this.username = username; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Spotlight.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Spotlight.java index 36f0c791350..ec57f9279c1 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Spotlight.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/Spotlight.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// The home screen's banner. One row, `home`. @Entity @@ -42,7 +43,7 @@ public class Spotlight { private String updatedBy = ""; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; public Spotlight() { } @@ -87,11 +88,11 @@ public void setUpdatedBy(String updatedBy) { this.updatedBy = updatedBy; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/StorePurchase.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/StorePurchase.java index 3941f4203e3..fab55e39ac5 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/StorePurchase.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/domain/StorePurchase.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A verified store transaction. The key is the store's transaction id, so a receipt can only ever be redeemed once. @Entity @@ -42,7 +43,7 @@ public class StorePurchase { private int gems; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public StorePurchase() { } @@ -87,11 +88,11 @@ public void setGems(int gems) { this.gems = gems; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/forge/Forge.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/forge/Forge.java index 940278c771f..6f37bc1269a 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/forge/Forge.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/forge/Forge.java @@ -65,6 +65,7 @@ import com.codenameone.examples.skirmish.rules.forge.Samples; import com.codenameone.examples.skirmish.rules.forge.Validator; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -140,7 +141,7 @@ public void seedOfficial() throws IOException { p = new ForgePack(); p.setId(official.id); p.setOwner(SYSTEM); - p.setCreatedAt(Clock.now()); + p.setCreatedAt(Instant.now()); } else if (!SYSTEM.equals(p.getOwner())) { return; } @@ -226,7 +227,7 @@ public PackSummaryDto saveDraft(String username, String content) throws IOExcept p.setId(pack.id); p.setOwner(username); p.setStatus(DRAFT); - p.setCreatedAt(Clock.now()); + p.setCreatedAt(Instant.now()); fillDraft(p, pack, username); packs.insert(p); } else { @@ -263,7 +264,7 @@ public PackSummaryDto delete(String username, boolean admin, String id) throws I } // Versions are kept: a replay names the version it was played on. p.setStatus(DELETED); - p.setUpdatedAt(Clock.now()); + p.setUpdatedAt(Instant.now()); packs.save(p); return summary(p); } @@ -368,7 +369,7 @@ public AssetDto upload(String username, AssetUploadDto file) throws IOException if (a != null) { return asset(a, false); } - long since = Clock.now() - Clock.DAY; + Instant since = Instant.now().minusMillis(Clock.DAY); if (assets.countByOwnerAndCreatedAtGreaterThan(username, since) >= MAX_UPLOADS_PER_DAY) { throw new ResponseStatusException(429, "That is enough uploads for today"); } @@ -381,7 +382,7 @@ public AssetDto upload(String username, AssetUploadDto file) throws IOException a.setStatus(PENDING); a.setAnimations(clip(join(animations), 2000)); a.setData(file.data()); - a.setCreatedAt(Clock.now()); + a.setCreatedAt(Instant.now()); assets.insert(a); return asset(a, false); } @@ -448,7 +449,7 @@ public MissionOutcomeDto result(String username, String encoded) throws IOExcept row.setStars(Math.max(row.getStars(), won)); int newStars = Math.max(0, won - row.getPaidStars()); row.setPaidStars(row.getPaidStars() + newStars); - row.setUpdatedAt(Clock.now()); + row.setUpdatedAt(Instant.now()); stars.save(row); p.setPlays(p.getPlays() + 1); packs.save(p); @@ -514,7 +515,7 @@ public PackSummaryDto packAction(String admin, String id, String action, String } else { throw new ResponseStatusException(400, "Unknown action"); } - p.setUpdatedAt(Clock.now()); + p.setUpdatedAt(Instant.now()); packs.save(p); record(admin, id, "PACK_" + action, reason); return summary(p); @@ -565,7 +566,7 @@ private void publishVersion(ForgePack p, ContentPack pack, boolean insert) throw v.setVersion(version); v.setHash(hash); v.setContent(canonical); - v.setPublishedAt(Clock.now()); + v.setPublishedAt(Instant.now()); versions.insert(v); p.setVersion(version); p.setHash(hash); @@ -578,7 +579,7 @@ private void publishVersion(ForgePack p, ContentPack pack, boolean insert) throw if (!HIDDEN.equals(p.getStatus())) { p.setStatus(PUBLISHED); } - p.setUpdatedAt(Clock.now()); + p.setUpdatedAt(Instant.now()); if (insert) { packs.insert(p); } else { @@ -659,7 +660,7 @@ private void fillDraft(ForgePack p, ContentPack pack, String username) throws IO p.setMissions(pack.missions.size()); p.setCards(pack.cards.size()); } - p.setUpdatedAt(Clock.now()); + p.setUpdatedAt(Instant.now()); } private static ContentPack parse(String content) { @@ -717,7 +718,7 @@ private void record(String admin, String target, String action, String reason) t a.setUsername(clip("pack:" + target, 190)); a.setAction(clip(action, 24)); a.setReason(clip(reason == null ? "" : reason, 255)); - a.setCreatedAt(Clock.now()); + a.setCreatedAt(Instant.now()); audit.insert(a); } @@ -737,7 +738,7 @@ static PackSummaryDto summary(ForgePack p) { int rating = p.getRatingCount() == 0 ? 0 : (p.getRatingSum() * 10 + p.getRatingCount() / 2) / p.getRatingCount(); return new PackSummaryDto(p.getId(), p.getName(), p.getAuthor(), p.getOwner(), p.getDescription(), p.getVersion(), p.getHash(), p.isOfficial(), p.getStatus(), p.getPlays(), rating, - p.getRatingCount(), p.getMissions(), p.getCards(), p.isPendingAssets(), p.getUpdatedAt()); + p.getRatingCount(), p.getMissions(), p.getCards(), p.isPendingAssets(), p.getUpdatedAt().toEpochMilli()); } private static AssetDto asset(ForgeAsset a, boolean withData) { diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/GameEndpoint.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/GameEndpoint.java index ce07979d380..27e652595cb 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/GameEndpoint.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/GameEndpoint.java @@ -92,7 +92,7 @@ public static List summaries(String me, List rows) out.add(new MatchSummaryDto(m.getId(), seat == 0 ? m.getPlayer1() : m.getPlayer0(), seat == 0 ? m.getName1() : m.getName0(), result, seat == 0 ? m.getCrowns0() : m.getCrowns1(), seat == 0 ? m.getCrowns1() : m.getCrowns0(), - seat == 0 ? m.getTrophies0() : m.getTrophies1(), m.getEndedAt(), m.getTicks())); + seat == 0 ? m.getTrophies0() : m.getTrophies1(), m.getEndedAt().toEpochMilli(), m.getTicks())); } return out; } @@ -107,7 +107,7 @@ public ReplayDto replay(String id) throws Exception { throw new ResponseStatusException(404, "No such match"); } return new ReplayDto(m.getId(), m.getPlayer0(), m.getPlayer1(), m.getName0(), m.getName1(), - m.getResult(), m.getCrowns0(), m.getCrowns1(), m.getReplay(), m.getRulesVersion(), m.getEndedAt()); + m.getResult(), m.getCrowns0(), m.getCrowns1(), m.getReplay(), m.getRulesVersion(), m.getEndedAt().toEpochMilli()); } @Override diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/GameTickets.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/GameTickets.java index 466e8db8bd4..149bfb0ae07 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/GameTickets.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/GameTickets.java @@ -28,6 +28,7 @@ import com.codenameone.examples.skirmish.repository.GameTicketRepository; import java.io.IOException; +import java.time.Instant; /// Tickets for the live channel. /// @@ -58,7 +59,7 @@ public TicketDto issue(String username) throws IOException { GameTicket row = new GameTicket(); row.setTicketHash(Ids.sha256(ticket)); row.setUsername(username); - row.setExpiresAt(System.currentTimeMillis() + TICKET_SECONDS * 1000L); + row.setExpiresAt(Instant.now().plusMillis(TICKET_SECONDS * 1000L)); tickets.insert(row); return new TicketDto(ticket, TICKET_SECONDS); } @@ -78,11 +79,11 @@ public String redeem(String ticket) throws IOException { return null; } String username = row.getUsername(); - long expiresAt = row.getExpiresAt(); + Instant expiresAt = row.getExpiresAt(); // One delete statement: the count it answers is what says this // connection, and not another presenting the same ticket, used it. int removed = tickets.deleteByTicketHash(hash); - if (removed != 1 || expiresAt < System.currentTimeMillis()) { + if (removed != 1 || expiresAt.isBefore(Instant.now())) { return null; } return username; @@ -92,7 +93,7 @@ public String redeem(String ticket) throws IOException { @Scheduled(fixedDelay = 60000, initialDelay = 60000) @Transactional public void sweep() throws IOException { - tickets.deleteByExpiresAtLessThan(System.currentTimeMillis()); + tickets.deleteByExpiresAtLessThan(Instant.now()); } /// Forgets the tickets of an account that is being closed. diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/Results.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/Results.java index ec5c1485c6f..bc63b076cad 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/Results.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/game/Results.java @@ -35,6 +35,7 @@ import com.codenameone.examples.skirmish.rules.RulesVersion; import com.codenameone.examples.skirmish.social.Referrals; import java.io.IOException; +import java.time.Instant; /// Records a finished match: the replay, and what it did to each player. // tag::skirmish-results[] @@ -134,7 +135,7 @@ Outcome[] save(MatchRoom room) throws IOException { p.setTrophies(p.getTrophies() + trophies); p.setCoins(p.getCoins() + coins); p.setLeftStreak(room.forfeit == i ? p.getLeftStreak() + 1 : 0); - p.setLastSeen(Clock.now()); + p.setLastSeen(Instant.now()); progression.afterMatch(p, result == i, result == Match.DRAW, room.match.player(i).crowns(), cards[i], spells[i]); profiles.save(p); @@ -152,7 +153,7 @@ Outcome[] save(MatchRoom room) throws IOException { m.setTrophies0(out[0].trophies); m.setTrophies1(out[1].trophies); m.setTicks(room.match.tick()); - m.setEndedAt(Clock.now()); + m.setEndedAt(Instant.now()); m.setRulesVersion(RulesVersion.ID); m.setReplay(replay.encode()); matches.insert(m); diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/push/PushDevices.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/push/PushDevices.java index e6a69f3e49a..6509bb30565 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/push/PushDevices.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/push/PushDevices.java @@ -30,6 +30,7 @@ import com.codenameone.examples.skirmish.repository.PushDeviceRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -112,7 +113,7 @@ private void makeRoom(String username) { while (held.size() >= MAX_PER_ACCOUNT) { PushDevice oldest = held.get(0); for (PushDevice each : held) { - if (each.getUpdatedAt() < oldest.getUpdatedAt()) { + if (each.getUpdatedAt().isBefore(oldest.getUpdatedAt())) { oldest = each; } } @@ -151,7 +152,7 @@ public List targetsOf(String username) { private static void fill(PushDevice row, String username, PushDeviceDto device, long now) { row.setUsername(username); row.setPlatform(Text.optional(device.platform(), 32, "the platform")); - row.setUpdatedAt(now); + row.setUpdatedAt(Instant.ofEpochMilli(now)); } /// The device as a target of the push service, which also spells its diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/BroadcastRepository.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/BroadcastRepository.java index 4cc3112a94e..5686c2c7e47 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/BroadcastRepository.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/BroadcastRepository.java @@ -23,6 +23,7 @@ import com.codename1.orm.repository.Query; import com.codename1.orm.repository.Repository; import com.codenameone.examples.skirmish.domain.Broadcast; +import java.time.Instant; import java.util.List; @Repository(entity = Broadcast.class, key = String.class) @@ -30,5 +31,5 @@ public interface BroadcastRepository extends CrudRepository { @Query("select b from Broadcast b order by b.sentAt desc, b.id asc") List newest(PageRequest page); - long countBySentAtGreaterThan(long since); + long countBySentAtGreaterThan(Instant since); } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/ForgeAssetRepository.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/ForgeAssetRepository.java index c18fe584309..9a252a5160c 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/ForgeAssetRepository.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/ForgeAssetRepository.java @@ -24,6 +24,7 @@ import com.codename1.orm.repository.Query; import com.codename1.orm.repository.Repository; import com.codenameone.examples.skirmish.domain.ForgeAsset; +import java.time.Instant; import java.util.List; @Repository(entity = ForgeAsset.class, key = String.class) @@ -31,5 +32,5 @@ public interface ForgeAssetRepository extends CrudRepository @Query("select a from ForgeAsset a where a.status = :s order by a.createdAt asc, a.sha256 asc") List inStatus(@Param("s") String status, PageRequest page); - long countByOwnerAndCreatedAtGreaterThan(String owner, long since); + long countByOwnerAndCreatedAtGreaterThan(String owner, Instant since); } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/GameTicketRepository.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/GameTicketRepository.java index f86069e9dd2..ad1d9594f8b 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/GameTicketRepository.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/GameTicketRepository.java @@ -21,6 +21,7 @@ import com.codename1.orm.repository.CrudRepository; import com.codename1.orm.repository.Repository; import com.codenameone.examples.skirmish.domain.GameTicket; +import java.time.Instant; /// The tickets that open a live connection. Only the hash of a ticket is /// stored, and it is the row's key. @@ -33,7 +34,7 @@ public interface GameTicketRepository extends CrudRepository int deleteByTicketHash(String ticketHash); /// Deletes the tickets that went stale before `now`. - int deleteByExpiresAtLessThan(long now); + int deleteByExpiresAtLessThan(Instant now); int deleteByUsername(String username); } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/MatchRecordRepository.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/MatchRecordRepository.java index c94f09d57e7..e9e8661499e 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/MatchRecordRepository.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/MatchRecordRepository.java @@ -24,6 +24,7 @@ import com.codename1.orm.repository.Query; import com.codename1.orm.repository.Repository; import com.codenameone.examples.skirmish.domain.MatchRecord; +import java.time.Instant; import java.util.List; @Repository(entity = MatchRecord.class, key = String.class) @@ -32,8 +33,8 @@ public interface MatchRecordRepository extends CrudRepository of(@Param("u") String username, PageRequest page); - long countByEndedAtGreaterThan(long since); + long countByEndedAtGreaterThan(Instant since); @Query("select m from MatchRecord m where m.endedAt >= :since") - List since(@Param("since") long since); + List since(@Param("since") Instant since); } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/ProfileRepository.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/ProfileRepository.java index e2c501941fc..c4f02bddf2d 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/ProfileRepository.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/ProfileRepository.java @@ -25,6 +25,7 @@ import com.codename1.orm.repository.Query; import com.codename1.orm.repository.Repository; import com.codenameone.examples.skirmish.domain.Profile; +import java.time.Instant; import java.util.List; @Repository(entity = Profile.class, key = String.class) @@ -44,15 +45,16 @@ public interface ProfileRepository extends CrudRepository { long countByFlaggedTrue(); @Query("select count(p) from Profile p where p.banned = true or p.suspendedUntil > :now") - Long suspended(@Param("now") long now); + Long suspended(@Param("now") Instant now); /// The players a broadcast reaches, a page at a time. Banned players are /// never sent anything; `seenBefore` and `joinedAfter` narrow it to the - /// lapsed and the new (pass 0 and `Long.MAX_VALUE` to leave them out). + /// lapsed and the new (pass `Instant.ofEpochMilli(Long.MAX_VALUE)` and + /// `Instant.ofEpochMilli(Long.MIN_VALUE)` to leave them out). @Query("select p from Profile p where p.banned = false and p.lastSeen < :seen and p.createdAt > :joined " + "order by p.username asc") - List audience(@Param("seen") long seenBefore, @Param("joined") long joinedAfter, PageRequest page); + List audience(@Param("seen") Instant seenBefore, @Param("joined") Instant joinedAfter, PageRequest page); @Query("select count(p) from Profile p where p.banned = false and p.lastSeen < :seen and p.createdAt > :joined") - Long audienceSize(@Param("seen") long seenBefore, @Param("joined") long joinedAfter); + Long audienceSize(@Param("seen") Instant seenBefore, @Param("joined") Instant joinedAfter); } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/StorePurchaseRepository.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/StorePurchaseRepository.java index ecff245a83d..2e9421728fd 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/StorePurchaseRepository.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/repository/StorePurchaseRepository.java @@ -23,6 +23,7 @@ import com.codename1.orm.repository.Query; import com.codename1.orm.repository.Repository; import com.codenameone.examples.skirmish.domain.StorePurchase; +import java.time.Instant; import java.util.List; @Repository(entity = StorePurchase.class, key = String.class) @@ -31,5 +32,5 @@ public interface StorePurchaseRepository extends CrudRepository of(@Param("u") String username); @Query("select s from StorePurchase s where s.createdAt >= :since") - List since(@Param("since") long since); + List since(@Param("since") Instant since); } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/shop/Shop.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/shop/Shop.java index a9339f80a96..0e448019e2f 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/shop/Shop.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/shop/Shop.java @@ -33,6 +33,7 @@ import com.codenameone.examples.skirmish.repository.ProfileRepository; import com.codenameone.examples.skirmish.repository.StorePurchaseRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -136,7 +137,7 @@ WalletDto redeem(String username, String store, ShopItemDto item, String transac row.setSku(item.sku()); int gems = Catalog.gems(item); row.setGems(gems); - row.setCreatedAt(Clock.now()); + row.setCreatedAt(Instant.now()); purchases.insert(row); if (gems > 0) { p.setGems(p.getGems() + gems); diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Audience.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Audience.java index 39fd4e0b0ec..3d41e789b5a 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Audience.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Audience.java @@ -118,9 +118,9 @@ public List filter(List all) { private int value(Profile p, String field) { switch (field) { case "daysAway": - return days(now - p.getLastSeen()); + return days(now - p.getLastSeen().toEpochMilli()); case "daysSinceJoin": - return days(now - p.getCreatedAt()); + return days(now - p.getCreatedAt().toEpochMilli()); case "trophies": return p.getTrophies(); case "battles": diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Insights.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Insights.java index 3830930bb64..bc56309d471 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Insights.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Insights.java @@ -36,6 +36,7 @@ import com.codenameone.examples.skirmish.repository.ProfileRepository; import com.codenameone.examples.skirmish.repository.ReferralRepository; import com.codenameone.examples.skirmish.repository.StorePurchaseRepository; +import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -80,15 +81,15 @@ public InsightsDto report(int days) { List all = profiles.findAll(); int[] joined = new int[n]; for (Profile p : all) { - bump(joined, first, p.getCreatedAt()); + bump(joined, first, p.getCreatedAt().toEpochMilli()); } int[] battles = new int[n]; List> fought = new ArrayList<>(); for (int i = 0; i < n; i++) { fought.add(new HashSet()); } - for (MatchRecord m : matches.since(first)) { - int d = dayIndex(first, m.getEndedAt(), n); + for (MatchRecord m : matches.since(Instant.ofEpochMilli(first))) { + int d = dayIndex(first, m.getEndedAt().toEpochMilli(), n); if (d >= 0) { battles[d]++; fought.get(d).add(m.getPlayer0()); @@ -106,10 +107,10 @@ public InsightsDto report(int days) { active[i] = fought.get(i).size(); } int[] gems = new int[n]; - List sales = purchases.since(0); + List sales = purchases.since(Instant.EPOCH); Set paid = new HashSet<>(); for (StorePurchase s : sales) { - int d = dayIndex(first, s.getCreatedAt(), n); + int d = dayIndex(first, s.getCreatedAt().toEpochMilli(), n); if (d >= 0) { gems[d] += s.getGems(); } @@ -149,9 +150,9 @@ private static List retention(List all, long now) { int cohort = 0; int back = 0; for (Profile p : all) { - if (p.getCreatedAt() <= now - span) { + if (p.getCreatedAt().toEpochMilli() <= now - span) { cohort++; - if (p.getLastSeen() - p.getCreatedAt() >= span) { + if (p.getLastSeen().toEpochMilli() - p.getCreatedAt().toEpochMilli() >= span) { back++; } } @@ -184,8 +185,8 @@ private static List bands(List all) { public QueryResultDto query(QueryDto q) { Audience audience = audience(q == null ? null : q.conditions()); List found = audience.filter(profiles.findAll()); - Collections.sort(found, (a, b) -> a.getLastSeen() < b.getLastSeen() ? -1 - : a.getLastSeen() > b.getLastSeen() ? 1 : a.getUsername().compareTo(b.getUsername())); + Collections.sort(found, (a, b) -> a.getLastSeen().isBefore(b.getLastSeen()) ? -1 + : a.getLastSeen().isAfter(b.getLastSeen()) ? 1 : a.getUsername().compareTo(b.getUsername())); List listed = new ArrayList<>(); for (int i = 0; i < found.size() && i < LISTED; i++) { listed.add(accounts.toDto(found.get(i))); @@ -197,7 +198,7 @@ public QueryResultDto query(QueryDto q) { /// the conditions may ask about. public Audience audience(List conditions) { Audience.check(conditions); - return Audience.of(conditions, purchases.since(0), referrals.findAll()); + return Audience.of(conditions, purchases.since(Instant.EPOCH), referrals.findAll()); } // end::skirmish-insights[] diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Pipelines.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Pipelines.java index 052009212fe..f94cf3aed94 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Pipelines.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Pipelines.java @@ -36,6 +36,7 @@ import com.codenameone.examples.skirmish.repository.PipelineRepository; import com.codenameone.examples.skirmish.repository.ProfileRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -108,7 +109,7 @@ public PipelineDto run(String id) throws IOException { for (Profile player : audience.filter(profiles.findAll())) { String key = p.getId() + ":" + player.getUsername(); PipelineHit hit = last.get(player.getUsername()); - if (hit != null && hit.getHitAt() > now - p.getCooldownDays() * Clock.DAY) { + if (hit != null && hit.getHitAt().toEpochMilli() > now - p.getCooldownDays() * Clock.DAY) { continue; } if (GEMS.equals(p.getAction())) { @@ -120,10 +121,10 @@ public PipelineDto run(String id) throws IOException { hit.setId(key); hit.setPipeline(p.getId()); hit.setUsername(player.getUsername()); - hit.setHitAt(now); + hit.setHitAt(Instant.ofEpochMilli(now)); hits.insert(hit); } else { - hit.setHitAt(now); + hit.setHitAt(Instant.ofEpochMilli(now)); hits.save(hit); } due.add(player.getUsername()); @@ -135,7 +136,7 @@ public PipelineDto run(String id) throws IOException { pushes.broadcast(due, Ids.next(), p.getTitle(), p.getBody(), p.getScreen(), "pipeline-" + p.getName()); } p.setReached(p.getReached() + due.size()); - p.setLastRun(now); + p.setLastRun(Instant.ofEpochMilli(now)); pipelines.save(p); return dto(p); } @@ -239,7 +240,7 @@ private static void check(PipelineDto d) { private static PipelineDto dto(Pipeline p) { List c = Audience.decode(p.getConditions()); return new PipelineDto(p.getId(), p.getName(), p.isEnabled(), c, p.getAction(), p.getTitle(), p.getBody(), - p.getScreen(), p.getAmount(), p.getCooldownDays(), p.getReached(), p.getLastRun()); + p.getScreen(), p.getAmount(), p.getCooldownDays(), p.getReached(), p.getLastRun().toEpochMilli()); } private void record(String admin, String action, String reason) throws IOException { @@ -249,7 +250,7 @@ private void record(String admin, String action, String reason) throws IOExcepti a.setUsername("promote"); a.setAction(action); a.setReason(reason.length() > 255 ? reason.substring(0, 255) : reason); - a.setCreatedAt(Clock.now()); + a.setCreatedAt(Instant.now()); audit.insert(a); } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Promotion.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Promotion.java index e90013eca96..f4c6f5d8a45 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Promotion.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Promotion.java @@ -40,6 +40,7 @@ import com.codenameone.examples.skirmish.repository.ReferralRepository; import com.codenameone.examples.skirmish.repository.SpotlightRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -121,7 +122,7 @@ public PromoteDto overview() throws IOException { sent.add(dto(b)); } return new PromoteDto((int) profiles.count(), - profiles.audienceSize(Long.MAX_VALUE, now - 7 * Clock.DAY).intValue(), + profiles.audienceSize(Instant.ofEpochMilli(Long.MAX_VALUE), Instant.ofEpochMilli(now - 7 * Clock.DAY)).intValue(), (int) referrals.count(), referrals.inState(Referrals.PLAYED).intValue(), top, sent, spotlightOf()); } @@ -138,7 +139,7 @@ public BroadcastDto audience(BroadcastDto b) throws IOException { public BroadcastDto broadcast(String admin, BroadcastDto b) throws IOException { check(b, true); long now = Clock.now(); - if (broadcasts.countBySentAtGreaterThan(now - Clock.DAY) >= MAX_BROADCASTS_PER_DAY) { + if (broadcasts.countBySentAtGreaterThan(Instant.ofEpochMilli(now - Clock.DAY)) >= MAX_BROADCASTS_PER_DAY) { throw new ResponseStatusException(429, "At most " + MAX_BROADCASTS_PER_DAY + " broadcasts a day: players who are pushed too often switch notifications off"); } @@ -157,7 +158,7 @@ public BroadcastDto broadcast(String admin, BroadcastDto b) throws IOException { row.setCampaign(campaign.length() > 40 ? campaign.substring(0, 40) : campaign); row.setTargets(reached); row.setSentBy(admin); - row.setSentAt(now); + row.setSentAt(Instant.ofEpochMilli(now)); broadcasts.insert(row); record(admin, "BROADCAST", b.segment() + ": " + b.title().trim()); return dto(row); @@ -185,7 +186,7 @@ public SpotlightDto spotlight(String admin, SpotlightDto s) throws IOException { row.setPackId(s.packId() == null ? "" : s.packId().trim()); row.setScreen(screen(s.screen())); row.setUpdatedBy(admin); - row.setUpdatedAt(Clock.now()); + row.setUpdatedAt(Instant.now()); if (fresh) { spotlights.insert(row); } else { @@ -198,7 +199,7 @@ public SpotlightDto spotlight(String admin, SpotlightDto s) throws IOException { private SpotlightDto spotlightOf() { Spotlight s = spotlights.findById(HOME); return s == null ? new SpotlightDto("", "", "", 0) - : new SpotlightDto(s.getMessage(), s.getPackId(), s.getScreen(), s.getUpdatedAt()); + : new SpotlightDto(s.getMessage(), s.getPackId(), s.getScreen(), s.getUpdatedAt().toEpochMilli()); } private List audienceOf(BroadcastDto b) { @@ -216,8 +217,8 @@ private List audienceOf(BroadcastDto b) { return out; } long now = Clock.now(); - long seen = LAPSED.equals(b.segment()) ? now - b.days() * Clock.DAY : Long.MAX_VALUE; - long joined = NEW.equals(b.segment()) ? now - b.days() * Clock.DAY : Long.MIN_VALUE; + Instant seen = Instant.ofEpochMilli(LAPSED.equals(b.segment()) ? now - b.days() * Clock.DAY : Long.MAX_VALUE); + Instant joined = Instant.ofEpochMilli(NEW.equals(b.segment()) ? now - b.days() * Clock.DAY : Long.MIN_VALUE); for (int page = 0; out.size() < MAX_AUDIENCE; page++) { List rows = profiles.audience(seen, joined, new PageRequest(page, PAGE)); for (Profile p : rows) { @@ -268,7 +269,7 @@ private static BroadcastDto with(BroadcastDto b, int targets, String by, long at private static BroadcastDto dto(Broadcast b) { return new BroadcastDto(b.getId(), b.getSegment(), b.getDays(), b.getTitle(), b.getBody(), b.getScreen(), - b.getCampaign(), b.getTargets(), b.getSentBy(), b.getSentAt()); + b.getCampaign(), b.getTargets(), b.getSentBy(), b.getSentAt().toEpochMilli()); } private void record(String admin, String action, String reason) throws IOException { @@ -278,7 +279,7 @@ private void record(String admin, String action, String reason) throws IOExcepti a.setUsername("promote"); a.setAction(action); a.setReason(reason.length() > 255 ? reason.substring(0, 255) : reason); - a.setCreatedAt(Clock.now()); + a.setCreatedAt(Instant.now()); audit.insert(a); } } diff --git a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Referrals.java b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Referrals.java index bec0d5b9d74..4c45b622668 100644 --- a/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Referrals.java +++ b/scripts/skirmish/backend/src/main/java/com/codenameone/examples/skirmish/social/Referrals.java @@ -37,6 +37,7 @@ import com.codenameone.examples.skirmish.repository.ReferralCodeRepository; import com.codenameone.examples.skirmish.repository.ReferralRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -95,7 +96,7 @@ public InviteDto invite(String username) throws IOException { ReferralCode c = new ReferralCode(); c.setCode(code); c.setUsername(username); - c.setCreatedAt(Clock.now()); + c.setCreatedAt(Instant.now()); codes.insert(c); } else { code = mine.get(0).getCode(); @@ -125,7 +126,7 @@ public RewardDto claim(String username, InviteClaimDto claim) throws IOException throw new ResponseStatusException(400, "You invited that player"); } Profile p = profiles.findById(username); - if (p == null || p.getCreatedAt() < Clock.now() - CLAIM_DAYS * Clock.DAY) { + if (p == null || p.getCreatedAt().isBefore(Instant.now().minusMillis(CLAIM_DAYS * Clock.DAY))) { throw new ResponseStatusException(400, "Invites count for new players only"); } Referral r = new Referral(); @@ -136,7 +137,7 @@ public RewardDto claim(String username, InviteClaimDto claim) throws IOException r.setChannel(clip(claim.channel(), 40)); r.setMatchType(clip(claim.match(), 20)); r.setState(JOINED); - r.setJoinedAt(Clock.now()); + r.setJoinedAt(Instant.now()); referrals.insert(r); Profile from = profiles.findById(inviter); pushes.friendJoined(inviter, p.getDisplayName()); @@ -154,7 +155,7 @@ public void played(String username) throws IOException { return; } r.setState(PLAYED); - r.setPlayedAt(Clock.now()); + r.setPlayedAt(Instant.now()); boolean pay = referrals.countByInviterAndRewardedTrue(r.getInviter()) < MAX_REWARDED; r.setRewarded(pay); referrals.save(r); @@ -173,7 +174,7 @@ public List friends(String username) throws IOException { Profile p = profiles.findById(r.getInvitee()); if (p != null) { out.add(new FriendDto(p.getDisplayName(), p.getTrophies(), r.getState(), r.isRewarded(), - r.getJoinedAt())); + r.getJoinedAt().toEpochMilli())); } } return out; diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/Accounts.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/Accounts.java index 533ae91da46..7308eb70487 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/Accounts.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/Accounts.java @@ -43,6 +43,7 @@ import com.codenameone.examples.wayline.repository.ProfileRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -152,7 +153,7 @@ private UserDto open(RegisterDto request) throws IOException { // older app asks -- begins an application, and the role waits for an // admin to approve it. create(username, request.password(), displayName, phone, false, vehicle, plate, false, - false, gender, System.currentTimeMillis()); + false, gender, Instant.now()); if (request.driver() || request.wantsToDrive()) { applications.open(username, vehicle, plate); } @@ -167,7 +168,7 @@ void create(String username, String password, String displayName, String phone, boolean phoneVerified, String vehicle, String plate, boolean driver, boolean admin) throws IOException { create(username, password, displayName, phone, phoneVerified, vehicle, plate, driver, - admin, GENDERS[0], System.currentTimeMillis()); + admin, GENDERS[0], Instant.now()); } /// As the method above, for a caller that also knows the gender and when @@ -177,7 +178,7 @@ void create(String username, String password, String displayName, String phone, @Transactional(rollbackFor = IOException.class) void create(String username, String password, String displayName, String phone, boolean phoneVerified, String vehicle, String plate, boolean driver, boolean admin, - String gender, long openedAt) throws IOException { + String gender, Instant openedAt) throws IOException { users.createUser(User.withUsername(username).password(encoder.encode(password)) .roles(roles(driver, admin)).build()); Profile profile = new Profile(); @@ -491,7 +492,7 @@ private void retire(String username) throws IOException { if (!closed.existsById(hash)) { ClosedAccount row = new ClosedAccount(); row.setUsernameHash(hash); - row.setClosedAt(System.currentTimeMillis()); + row.setClosedAt(Instant.now()); closed.insert(row); } } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/DemoAccounts.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/DemoAccounts.java index e2a2ea122e4..7a7190b9614 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/DemoAccounts.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/DemoAccounts.java @@ -40,6 +40,7 @@ import com.codenameone.examples.wayline.ride.Fares; import java.io.IOException; +import java.time.Instant; /// The accounts a server starts with. /// @@ -169,7 +170,7 @@ void flag(String username, String why, int daysAgo) throws IOException { profile.setFlagged(true); profile.setFlagReason(why); moderation.record(username, ADMIN, Moderation.FLAG, why, - System.currentTimeMillis() - daysAgo * Days.MILLIS); + Instant.now().minusMillis(daysAgo * Days.MILLIS)); } /// An admin, or the plainest kind of account. @@ -231,7 +232,7 @@ private void driver(String username, String name, String phone, String gender, S void approved(String username, String name, String product, String colour, String make, String model, String plate, int seats, boolean wheelchair, boolean pets, int daysAgo) throws IOException { - long handedIn = System.currentTimeMillis() - (daysAgo + 1) * Days.MILLIS; + Instant handedIn = Instant.now().minusMillis((daysAgo + 1) * Days.MILLIS); DriverApplication form = forms.findById(username); form.setLegalName(name); form.setDateOfBirth("1988-04-12"); @@ -291,13 +292,13 @@ private void applicant() throws IOException { @Transactional(rollbackFor = IOException.class) void handedIn(String username, int daysAgo) throws IOException { DriverApplication form = forms.findById(username); - form.setSubmittedAt(System.currentTimeMillis() - daysAgo * Days.MILLIS); + form.setSubmittedAt(Instant.now().minusMillis(daysAgo * Days.MILLIS)); } /// When an account opened that many days ago was opened, so that the chart /// of new accounts is not one bar. - private static long opened(int daysAgo) { - return System.currentTimeMillis() - daysAgo * Days.MILLIS; + private static Instant opened(int daysAgo) { + return Instant.now().minusMillis(daysAgo * Days.MILLIS); } private static int year() { diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/Moderation.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/Moderation.java index 08d0a5c220d..844c4753e22 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/Moderation.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/Moderation.java @@ -26,6 +26,7 @@ import com.codenameone.examples.wayline.repository.ModerationEventRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -57,15 +58,16 @@ public void record(String username, String by, String action, String reason) // came with it -- would otherwise be listed in either order. The later // one is stamped after the one before it, so the list is the order in // which things were done. - Long newest = events.newest(username); - long after = newest == null ? 0L : newest.longValue() + 1L; - record(username, by, action, reason, Math.max(System.currentTimeMillis(), after)); + Instant newest = events.newest(username); + Instant now = Instant.now(); + Instant stamp = newest != null && !newest.isBefore(now) ? newest.plusMillis(1L) : now; + record(username, by, action, reason, stamp); } /// As [#record(String, String, String, String)], at a time of the caller's /// choosing; the demo data is the one caller that has a past to write. @Transactional - public void record(String username, String by, String action, String reason, long at) + public void record(String username, String by, String action, String reason, Instant at) throws IOException { String why = reason == null ? "" : reason.trim(); ModerationEvent event = new ModerationEvent(); @@ -85,8 +87,8 @@ public List events(String username) throws IOException { List out = new ArrayList(); for (int iter = 0; iter < rows.size(); iter++) { ModerationEvent row = rows.get(iter); - out.add(new ModerationEventDto(row.getCreatedAt(), row.getActor(), row.getAction(), - row.getReason())); + out.add(new ModerationEventDto(row.getCreatedAt().toEpochMilli(), row.getActor(), + row.getAction(), row.getReason())); } return out; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/PhoneVerification.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/PhoneVerification.java index 10ed791a384..1c53c360b64 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/PhoneVerification.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/account/PhoneVerification.java @@ -31,6 +31,7 @@ import com.codenameone.examples.wayline.sms.SmsSender; import java.io.IOException; +import java.time.Instant; /// Proves an account's phone number by texting it a code. /// @@ -72,7 +73,7 @@ public PhoneChallengeDto start(String username) throws IOException { UserDto user = accounts.describe(username); String code = newCode(); String codeHash = hash(username, code); - store(username, codeHash, System.currentTimeMillis()); + store(username, codeHash, Instant.now()); try { sms.send(user.phone(), "Your Wayline code is " + code); } catch (IOException failed) { @@ -98,20 +99,20 @@ public PhoneChallengeDto start(String username) throws IOException { /// one is kept, so at most two codes are live, and only one whose guesses /// were not used up. @Transactional - void store(String username, String codeHash, long now) throws IOException { + void store(String username, String codeHash, Instant now) throws IOException { // Before the code is read: two requests for one account take turns, // so the second finds the code the first just stored and is told to // wait. Otherwise both pass the check below and both send a text. accounts.hold(username); PhoneCode pending = codes.findById(username); - if (pending != null && now - pending.getSentAt() < RESEND_SECONDS * 1000L) { + if (pending != null && pending.getSentAt().plusSeconds(RESEND_SECONDS).isAfter(now)) { throw new ResponseStatusException(429, "Wait a moment before asking for another code"); } boolean first = pending == null; if (first) { pending = new PhoneCode(); pending.setUsername(username); - } else if (pending.getExpiresAt() >= now && pending.getAttempts() < MAX_ATTEMPTS) { + } else if (!pending.getExpiresAt().isBefore(now) && pending.getAttempts() < MAX_ATTEMPTS) { // With the guesses it has used: asking for another code must not // buy the old one a fresh set. pending.setPreviousHash(pending.getCodeHash()); @@ -119,11 +120,11 @@ void store(String username, String codeHash, long now) throws IOException { pending.setPreviousAttempts(pending.getAttempts()); } else { pending.setPreviousHash(""); - pending.setPreviousExpiresAt(0L); + pending.setPreviousExpiresAt(Instant.EPOCH); pending.setPreviousAttempts(0); } pending.setCodeHash(codeHash); - pending.setExpiresAt(now + CODE_SECONDS * 1000L); + pending.setExpiresAt(now.plusSeconds(CODE_SECONDS)); pending.setAttempts(0); pending.setSentAt(now); if (first) { @@ -148,7 +149,7 @@ void discard(String username, String codeHash) throws IOException { return; } if (pending.getPreviousHash().length() == 0 - || pending.getPreviousExpiresAt() < System.currentTimeMillis()) { + || pending.getPreviousExpiresAt().isBefore(Instant.now())) { codes.deleteById(username); return; } @@ -156,9 +157,9 @@ void discard(String username, String codeHash) throws IOException { pending.setExpiresAt(pending.getPreviousExpiresAt()); pending.setAttempts(pending.getPreviousAttempts()); pending.setPreviousHash(""); - pending.setPreviousExpiresAt(0L); + pending.setPreviousExpiresAt(Instant.EPOCH); pending.setPreviousAttempts(0); - pending.setSentAt(0L); + pending.setSentAt(Instant.EPOCH); } /// Checks the code the user typed. Answers 400 for a wrong or expired one @@ -186,7 +187,7 @@ boolean guess(String username, String code) throws IOException { // row the other has. accounts.hold(username); PhoneCode pending = codes.findById(username); - if (pending == null || pending.getExpiresAt() < System.currentTimeMillis()) { + if (pending == null || pending.getExpiresAt().isBefore(Instant.now())) { throw new ResponseStatusException(400, "That code has expired. Ask for a new one"); } if (pending.getAttempts() >= MAX_ATTEMPTS) { @@ -222,7 +223,7 @@ boolean guess(String username, String code) throws IOException { boolean previous = Crypto.equalsConstantTime(given, pending.getPreviousHash().getBytes("UTF-8")) && pending.getPreviousHash().length() > 0 - && pending.getPreviousExpiresAt() >= System.currentTimeMillis() + && !pending.getPreviousExpiresAt().isBefore(Instant.now()) && counted != null && counted.getPreviousAttempts() <= MAX_ATTEMPTS; if (!current && !previous) { return false; diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/admin/Statistics.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/admin/Statistics.java index c8a89ce9e44..7f15a0b03c3 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/admin/Statistics.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/admin/Statistics.java @@ -44,6 +44,7 @@ import com.codenameone.examples.wayline.ride.Matcher; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -116,8 +117,9 @@ public AdminStatsDto dashboard() throws IOException { } } int online = (int) cars.countByOnlineTrueAndLastSeenGreaterThanEqual( - now - Matcher.FRESH_MILLIS); - int today = (int) rides.countByRequestedAtGreaterThanEqual(Days.start(now)); + Instant.ofEpochMilli(now - Matcher.FRESH_MILLIS)); + int today = (int) rides.countByRequestedAtGreaterThanEqual( + Instant.ofEpochMilli(Days.start(now))); int active = (int) rides.countByStateIn(ACTIVE); int done = (int) rides.countByStateIn(new RideState[] {RideState.COMPLETED}); long revenue = Rows.number(rides.fares(RideState.COMPLETED, PAID)); @@ -141,10 +143,11 @@ public StatsSeriesDto series(int days) throws IOException { int[] byHour = new int[24]; // By day and by hour, counted here from one row per ride. Map requestedAt = new HashMap(); - List timeline = rides.timeline(since); + Instant from = Instant.ofEpochMilli(since); + List timeline = rides.timeline(from); for (int iter = 0; iter < timeline.size(); iter++) { Object[] ride = timeline.get(iter); - long at = whole(ride[1]); + long at = millis(ride[1]); RideState state = Rows.state(ride[2]); requestedAt.put(Rows.text(ride[0]), Long.valueOf(at)); int index = (int) ((at - since) / Days.MILLIS); @@ -166,7 +169,7 @@ public StatsSeriesDto series(int days) throws IOException { int[] byState = new int[STATES.length]; long completed = 0L; long finished = 0L; - List states = rides.countByState(since); + List states = rides.countByState(from); for (int iter = 0; iter < states.size(); iter++) { RideState state = Rows.state(states.get(iter)[0]); long count = whole(states.get(iter)[1]); @@ -183,7 +186,7 @@ public StatsSeriesDto series(int days) throws IOException { } } int[] byProduct = new int[Fares.PRODUCTS.length]; - List products = rides.countByProduct(since); + List products = rides.countByProduct(from); for (int iter = 0; iter < products.size(); iter++) { for (int p = 0; p < Fares.PRODUCTS.length; p++) { if (Fares.PRODUCTS[p].equals(products.get(iter)[0])) { @@ -192,12 +195,12 @@ public StatsSeriesDto series(int days) throws IOException { } } Map completedBy = new HashMap(); - List perDriver = rides.countByDriver(since, RideState.COMPLETED); + List perDriver = rides.countByDriver(from, RideState.COMPLETED); for (int iter = 0; iter < perDriver.size(); iter++) { completedBy.put(Rows.text(perDriver.get(iter)[0]), new int[] {(int) whole(perDriver.get(iter)[1])}); } - long fareSum = Rows.number(rides.faresSince(since, RideState.COMPLETED)); + long fareSum = Rows.number(rides.faresSince(from, RideState.COMPLETED)); List hours = new ArrayList(); for (int iter = 0; iter < byHour.length; iter++) { hours.add(Integer.valueOf(byHour[iter])); @@ -219,9 +222,9 @@ public StatsSeriesDto series(int days) throws IOException { double completionRate = finished == 0L ? 0d : Math.round(completed * 100d / finished) / 100d; - List signUps = profiles.signUps(since); + List signUps = profiles.signUps(from); for (int iter = 0; iter < signUps.size(); iter++) { - int index = (int) ((signUps.get(iter).longValue() - since) / Days.MILLIS); + int index = (int) ((signUps.get(iter).toEpochMilli() - since) / Days.MILLIS); if (index >= 0 && index < span) { dayNewUsers[index]++; } @@ -235,13 +238,13 @@ public StatsSeriesDto series(int days) throws IOException { // How long a rider waited for a driver to take the ride: each time one // was accepted, set against when it was asked for. - List waits = events.reached(since, RideState.ACCEPTED); + List waits = events.reached(from, RideState.ACCEPTED); long waited = 0L; int answered = 0; for (int iter = 0; iter < waits.size(); iter++) { Long asked = requestedAt.get(Rows.text(waits.get(iter)[0])); if (asked != null) { - waited += Math.max(0L, whole(waits.get(iter)[1]) - asked.longValue()); + waited += Math.max(0L, millis(waits.get(iter)[1]) - asked.longValue()); answered++; } } @@ -297,6 +300,14 @@ private static boolean cancelled(RideState state) { || RideState.CANCELLED_BY_ADMIN == state; } + /// A time as a query answers it, in milliseconds since the epoch. + private static long millis(Object value) { + if (!(value instanceof Instant)) { + throw new IllegalStateException("Not a time: " + value); + } + return ((Instant) value).toEpochMilli(); + } + /// A count or a sum as a query answers it. private static long whole(Object value) { return value instanceof Number ? ((Number) value).longValue() : 0L; diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/ClosedAccount.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/ClosedAccount.java index 88afe0cfffd..ccc84fe5bdb 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/ClosedAccount.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/ClosedAccount.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// What is left of an account that was closed: the hash of its e-mail, kept so /// that the address cannot be registered again. @@ -31,7 +32,7 @@ public class ClosedAccount { private String usernameHash = ""; @Column(nullable = false) - private long closedAt; + private Instant closedAt = Instant.EPOCH; public ClosedAccount() { } @@ -44,11 +45,11 @@ public void setUsernameHash(String usernameHash) { this.usernameHash = usernameHash; } - public long getClosedAt() { + public Instant getClosedAt() { return closedAt; } - public void setClosedAt(long closedAt) { + public void setClosedAt(Instant closedAt) { this.closedAt = closedAt; } } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverApplication.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverApplication.java index 7cc3acad6c8..939786f2446 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverApplication.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverApplication.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An account's application to drive, and what became of it. @Entity @@ -75,13 +76,13 @@ public class DriverApplication { private String rejectionReason = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) - private long submittedAt; + private Instant submittedAt = Instant.EPOCH; @Column(nullable = false) - private long reviewedAt; + private Instant reviewedAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(190)") private String reviewedBy = ""; @@ -217,27 +218,27 @@ public void setRejectionReason(String rejectionReason) { this.rejectionReason = rejectionReason; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public long getSubmittedAt() { + public Instant getSubmittedAt() { return submittedAt; } - public void setSubmittedAt(long submittedAt) { + public void setSubmittedAt(Instant submittedAt) { this.submittedAt = submittedAt; } - public long getReviewedAt() { + public Instant getReviewedAt() { return reviewedAt; } - public void setReviewedAt(long reviewedAt) { + public void setReviewedAt(Instant reviewedAt) { this.reviewedAt = reviewedAt; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverDocument.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverDocument.java index 893c17c14f4..565daaf0805 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverDocument.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverDocument.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A document an applicant uploaded, one of each kind. `data` is the file in /// Base64, which is text on every database. @@ -41,7 +42,7 @@ public class DriverDocument { private String status = ""; @Column(nullable = false) - private long uploadedAt; + private Instant uploadedAt = Instant.EPOCH; @Column(nullable = false) private String data = ""; @@ -81,11 +82,11 @@ public void setStatus(String status) { this.status = status; } - public long getUploadedAt() { + public Instant getUploadedAt() { return uploadedAt; } - public void setUploadedAt(long uploadedAt) { + public void setUploadedAt(Instant uploadedAt) { this.uploadedAt = uploadedAt; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverState.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverState.java index 28a89341862..19e92bad01f 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverState.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/DriverState.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// Where a driver's car is, whether they are on line, and what riders made of them. @Entity @@ -42,7 +43,7 @@ public class DriverState { private double heading; @Column(nullable = false) - private long lastSeen; + private Instant lastSeen = Instant.EPOCH; @Column(nullable = false) private long ratingSum; @@ -98,11 +99,11 @@ public void setHeading(double heading) { this.heading = heading; } - public long getLastSeen() { + public Instant getLastSeen() { return lastSeen; } - public void setLastSeen(long lastSeen) { + public void setLastSeen(Instant lastSeen) { this.lastSeen = lastSeen; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/LiveTicket.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/LiveTicket.java index 64fa22794f3..62847a03e56 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/LiveTicket.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/LiveTicket.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A ticket for one connection to the live channel, as its hash. @Entity @@ -33,7 +34,7 @@ public class LiveTicket { private String username = ""; @Column(nullable = false) - private long expiresAt; + private Instant expiresAt = Instant.EPOCH; public LiveTicket() { } @@ -54,11 +55,11 @@ public void setUsername(String username) { this.username = username; } - public long getExpiresAt() { + public Instant getExpiresAt() { return expiresAt; } - public void setExpiresAt(long expiresAt) { + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/ModerationEvent.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/ModerationEvent.java index 56cf4f985eb..b6509c576c8 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/ModerationEvent.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/ModerationEvent.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One thing an admin did to an account, and why. Written once, never changed. @Entity @@ -33,7 +34,7 @@ public class ModerationEvent { private String username = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(190)") private String actor = ""; @@ -63,11 +64,11 @@ public void setUsername(String username) { this.username = username; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Payment.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Payment.java index 5fffb1fe321..84e32e0d6b8 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Payment.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Payment.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// What a completed ride was charged, and what was given back. @Entity @@ -42,7 +43,7 @@ public class Payment { private String providerRef = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(64)") private String tipRef = ""; @@ -57,7 +58,7 @@ public class Payment { private String refundReason = ""; @Column(nullable = false) - private long refundedAt; + private Instant refundedAt = Instant.EPOCH; public Payment() { } @@ -102,11 +103,11 @@ public void setProviderRef(String providerRef) { this.providerRef = providerRef; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } @@ -142,11 +143,11 @@ public void setRefundReason(String refundReason) { this.refundReason = refundReason; } - public long getRefundedAt() { + public Instant getRefundedAt() { return refundedAt; } - public void setRefundedAt(long refundedAt) { + public void setRefundedAt(Instant refundedAt) { this.refundedAt = refundedAt; } } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PaymentMethod.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PaymentMethod.java index 45f6f0e8ec5..8ce68550890 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PaymentMethod.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PaymentMethod.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A saved card: what the provider calls it and what to show for it. The /// number itself is never here. @@ -52,7 +53,7 @@ public class PaymentMethod { private boolean preferred; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public PaymentMethod() { } @@ -121,11 +122,11 @@ public void setPreferred(boolean preferred) { this.preferred = preferred; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PaymentSetup.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PaymentSetup.java index 22a6a37ad10..595124dfb85 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PaymentSetup.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PaymentSetup.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A card being added on the provider's page, until the browser comes back. @Entity @@ -36,7 +37,7 @@ public class PaymentSetup { private String reference = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false) private boolean completed; @@ -68,11 +69,11 @@ public void setReference(String reference) { this.reference = reference; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Payout.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Payout.java index 0a1ebaa393c..46b49521a8d 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Payout.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Payout.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// One payment of earnings to a driver. @Entity @@ -39,7 +40,7 @@ public class Payout { private String status = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(120)") private String destination = ""; @@ -79,11 +80,11 @@ public void setStatus(String status) { this.status = status; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PhoneCode.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PhoneCode.java index 8547e5f09a4..c3bed31bb96 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PhoneCode.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PhoneCode.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// The verification code an account was last sent, as its hash. @Entity @@ -33,20 +34,20 @@ public class PhoneCode { private String codeHash = ""; @Column(nullable = false) - private long expiresAt; + private Instant expiresAt = Instant.EPOCH; @Column(nullable = false) private int attempts; @Column(nullable = false) - private long sentAt; + private Instant sentAt = Instant.EPOCH; /// The code sent before this one, while it is still good, or empty. @Column(nullable = false, type = "VARCHAR(64)") private String previousHash = ""; @Column(nullable = false) - private long previousExpiresAt; + private Instant previousExpiresAt = Instant.EPOCH; /// The guesses already taken at the code before, which keeps the budget /// it had rather than starting a new one when another code is sent. @@ -72,11 +73,11 @@ public void setCodeHash(String codeHash) { this.codeHash = codeHash; } - public long getExpiresAt() { + public Instant getExpiresAt() { return expiresAt; } - public void setExpiresAt(long expiresAt) { + public void setExpiresAt(Instant expiresAt) { this.expiresAt = expiresAt; } @@ -88,11 +89,11 @@ public void setAttempts(int attempts) { this.attempts = attempts; } - public long getSentAt() { + public Instant getSentAt() { return sentAt; } - public void setSentAt(long sentAt) { + public void setSentAt(Instant sentAt) { this.sentAt = sentAt; } @@ -104,11 +105,11 @@ public void setPreviousHash(String previousHash) { this.previousHash = previousHash; } - public long getPreviousExpiresAt() { + public Instant getPreviousExpiresAt() { return previousExpiresAt; } - public void setPreviousExpiresAt(long previousExpiresAt) { + public void setPreviousExpiresAt(Instant previousExpiresAt) { this.previousExpiresAt = previousExpiresAt; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Pricing.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Pricing.java index f9c57e3bae9..df169909ed4 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Pricing.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Pricing.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// The prices an admin set. One row, with the id 1, once they have set any. @Entity @@ -57,7 +58,7 @@ public class Pricing { private double xl; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(190)") private String updatedBy = ""; @@ -145,11 +146,11 @@ public void setXl(double xl) { this.xl = xl; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Profile.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Profile.java index e58122895bb..3576a87c28c 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Profile.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Profile.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// An account's profile: who it is to the people it rides with. /// @@ -48,7 +49,7 @@ public class Profile { private String plate = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; @Column(nullable = false, type = "VARCHAR(16)") private String gender = "unspecified"; @@ -125,11 +126,11 @@ public void setPlate(String plate) { this.plate = plate; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PushDevice.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PushDevice.java index 88f00470019..fb84f6e8cc2 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PushDevice.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/PushDevice.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// A device an account is sent push notifications on. /// @@ -46,7 +47,7 @@ public class PushDevice { private String platform = ""; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; public PushDevice() { } @@ -91,11 +92,11 @@ public void setPlatform(String platform) { this.platform = platform; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Ride.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Ride.java index 02537248968..aba0a2ce4ae 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Ride.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/Ride.java @@ -22,6 +22,7 @@ import com.codename1.annotations.Entity; import com.codename1.annotations.Id; import com.codenameone.examples.wayline.api.RideState; +import java.time.Instant; // tag::wayline-entity[] /// A ride, from the request to its end. @@ -75,16 +76,16 @@ public class Ride { private double durationSeconds; @Column(nullable = false) - private long requestedAt; + private Instant requestedAt = Instant.EPOCH; @Column(nullable = false) - private long updatedAt; + private Instant updatedAt = Instant.EPOCH; @Column(nullable = false) - private long offerExpiresAt; + private Instant offerExpiresAt = Instant.EPOCH; @Column(nullable = false) - private long searchUntil; + private Instant searchUntil = Instant.EPOCH; @Column(nullable = false, type = "SMALLINT") private int stars; @@ -251,35 +252,35 @@ public void setDurationSeconds(double durationSeconds) { this.durationSeconds = durationSeconds; } - public long getRequestedAt() { + public Instant getRequestedAt() { return requestedAt; } - public void setRequestedAt(long requestedAt) { + public void setRequestedAt(Instant requestedAt) { this.requestedAt = requestedAt; } - public long getUpdatedAt() { + public Instant getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(long updatedAt) { + public void setUpdatedAt(Instant updatedAt) { this.updatedAt = updatedAt; } - public long getOfferExpiresAt() { + public Instant getOfferExpiresAt() { return offerExpiresAt; } - public void setOfferExpiresAt(long offerExpiresAt) { + public void setOfferExpiresAt(Instant offerExpiresAt) { this.offerExpiresAt = offerExpiresAt; } - public long getSearchUntil() { + public Instant getSearchUntil() { return searchUntil; } - public void setSearchUntil(long searchUntil) { + public void setSearchUntil(Instant searchUntil) { this.searchUntil = searchUntil; } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/RideActivity.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/RideActivity.java index 1267299dc02..a81a5bd26d2 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/RideActivity.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/RideActivity.java @@ -21,6 +21,7 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; +import java.time.Instant; /// The Live Activity a rider's phone shows a ride in, while the ride lasts. @Entity @@ -38,12 +39,12 @@ public class RideActivity { /// When the server last sent it a state, for spacing out the updates. @Column(nullable = false) - private long sentAt; + private Instant sentAt = Instant.EPOCH; /// When its ride ended, 0 while the ride lasts. An ended activity is kept /// until the phone has been told to end it. @Column(nullable = false) - private long endedAt; + private Instant endedAt = Instant.EPOCH; public RideActivity() { } @@ -72,19 +73,19 @@ public void setActivityId(String activityId) { this.activityId = activityId; } - public long getSentAt() { + public Instant getSentAt() { return sentAt; } - public void setSentAt(long sentAt) { + public void setSentAt(Instant sentAt) { this.sentAt = sentAt; } - public long getEndedAt() { + public Instant getEndedAt() { return endedAt; } - public void setEndedAt(long endedAt) { + public void setEndedAt(Instant endedAt) { this.endedAt = endedAt; } } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/RideEvent.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/RideEvent.java index 4f96ce29a5a..134411957ce 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/RideEvent.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/domain/RideEvent.java @@ -22,6 +22,7 @@ import com.codename1.annotations.Entity; import com.codename1.annotations.Id; import com.codenameone.examples.wayline.api.RideState; +import java.time.Instant; /// One change of a ride's state: what it became, who made it so, and when. @Entity @@ -40,7 +41,7 @@ public class RideEvent { private String actor = ""; @Column(nullable = false) - private long createdAt; + private Instant createdAt = Instant.EPOCH; public RideEvent() { } @@ -77,11 +78,11 @@ public void setActor(String actor) { this.actor = actor; } - public long getCreatedAt() { + public Instant getCreatedAt() { return createdAt; } - public void setCreatedAt(long createdAt) { + public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driver/Drivers.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driver/Drivers.java index 814a136912f..b084ccd10a1 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driver/Drivers.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driver/Drivers.java @@ -47,6 +47,7 @@ import com.codenameone.examples.wayline.ride.Matcher; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -147,7 +148,7 @@ private Report store(String driver, DriverStatusDto status) throws IOException { if (!status.online() && ride != null) { throw new ResponseStatusException(409, "Finish the ride before going off line"); } - long now = System.currentTimeMillis(); + Instant now = Instant.now(); DriverState state = drivers.findById(driver); // The time since the last report was time on line, unless it was so // long ago that the app had plainly stopped reporting. It is counted @@ -156,7 +157,8 @@ private Report store(String driver, DriverStatusDto status) throws IOException { // is, so the row read here stays managed and its change is written // either way; a statement marked clearAutomatically would detach it, // and a change made after that would be lost. - long since = state != null && state.isOnline() ? now - state.getLastSeen() : 0L; + long since = state != null && state.isOnline() + ? now.toEpochMilli() - state.getLastSeen().toEpochMilli() : 0L; boolean first = state == null; if (first) { state = new DriverState(); @@ -177,7 +179,7 @@ private Report store(String driver, DriverStatusDto status) throws IOException { if (since > 0L && since < Matcher.FRESH_MILLIS) { // Cut at midnight: a stretch on line across it belongs half to // each day, not all to the new one. - long[] days = Days.split(now - since, now); + long[] days = Days.split(now.toEpochMilli() - since, now.toEpochMilli()); for (int iter = 0; iter < days.length; iter += 2) { addHours(driver, days[iter], days[iter + 1]); } @@ -282,10 +284,11 @@ public EarningsDto earnings(String driver) throws IOException { long now = System.currentTimeMillis(); // The day's trips and the day's money from one query, so the header // that shows them together counts the rides that made the sum. - Object[] day = rides.paidTotalsSince(driver, now - now % DAY_MILLIS); + Object[] day = rides.paidTotalsSince(driver, Instant.ofEpochMilli(now - now % DAY_MILLIS)); int todayCount = day == null ? 0 : (int) Rows.number(day[0]); long today = day == null ? 0L : Rows.number(day[1]); - long week = Rows.number(rides.paidSince(driver, now - 7 * DAY_MILLIS)); + long week = Rows.number( + rides.paidSince(driver, Instant.ofEpochMilli(now - 7 * DAY_MILLIS))); Object[] total = rides.paidTotals(driver); int count = total == null ? 0 : (int) Rows.number(total[0]); long all = total == null ? 0L : Rows.number(total[1]); @@ -309,7 +312,7 @@ private static DriverDto toDto(Profile profile, DriverApplication application, double rating = 5d; long lastSeen = 0L; if (car != null) { - lastSeen = car.getLastSeen(); + lastSeen = car.getLastSeen().toEpochMilli(); // On line means said so and heard from lately; see Matcher. online = car.isOnline() && System.currentTimeMillis() - lastSeen < Matcher.FRESH_MILLIS; diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driver/Earnings.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driver/Earnings.java index 500767060fe..f1ecda06185 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driver/Earnings.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driver/Earnings.java @@ -48,6 +48,7 @@ import com.codenameone.examples.wayline.ride.Fares; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -110,16 +111,16 @@ public EarningsSummaryDto summary(String driver) throws IOException { long monthStart = today - 29 * Days.MILLIS; long weekStart = today - 6 * Days.MILLIS; List done = rides.findByDriverAndStateAndUpdatedAtGreaterThanEqual(driver, - RideState.COMPLETED, monthStart); + RideState.COMPLETED, Instant.ofEpochMilli(monthStart)); // A card tip is on its ride from the moment it is asked for, and is // still there when the processor never answered. Only one whose charge // is on record is earned, here as in the balance: otherwise a day's // total would show money that cannot be cashed out. Set charged = new HashSet( - rides.tipChargedSince(driver, monthStart)); + rides.tipChargedSince(driver, Instant.ofEpochMilli(monthStart))); for (int iter = 0; iter < done.size(); iter++) { Ride ride = done.get(iter); - long at = ride.getUpdatedAt(); + long at = ride.getUpdatedAt().toEpochMilli(); boolean tipped = "cash".equals(ride.getMethodId()) || charged.contains(ride.getId()); // The fare likewise counts only once it is paid, as in the balance: // a card charge that failed, was refunded or has not come back is @@ -192,7 +193,7 @@ public PayoutDto cashOut(String driver) throws IOException { row.setDriver(driver); row.setAmountCents(amount); row.setStatus("paid"); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); row.setDestination(account.getBankName() + " ****" + account.getLast4()); payouts.insert(row); return toDto(row); @@ -291,6 +292,6 @@ private static PayoutAccountDto toDto(PayoutAccount row) { private static PayoutDto toDto(Payout row) { return new PayoutDto(row.getId(), row.getAmountCents(), row.getStatus(), - row.getCreatedAt(), row.getDestination()); + row.getCreatedAt().toEpochMilli(), row.getDestination()); } } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driving/Applications.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driving/Applications.java index 3a7e343e68a..0831bcf2439 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driving/Applications.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/driving/Applications.java @@ -45,6 +45,7 @@ import com.codenameone.examples.wayline.ride.Fares; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -254,7 +255,7 @@ public DriverApplicationDto upload(String username, DocumentUploadDto upload) // looked at the one it replaced. hold(username); editable(username); - long now = System.currentTimeMillis(); + Instant now = Instant.now(); // Replaced with a statement where there is one already, so the picture // it held is not read only to be overwritten. if (documents.replace(username, kind, type, "uploaded", now, data) == 0) { @@ -325,7 +326,7 @@ public DriverApplicationDto submit(String username) throws IOException { throw new ResponseStatusException(400, what.toString()); } // Held to the status it was read in: handed in twice, it is handed in once. - applications.submit(username, was, PENDING, System.currentTimeMillis()); + applications.submit(username, was, PENDING, Instant.now()); return get(username); } @@ -439,7 +440,7 @@ public void grant(String by, String username) throws IOException { applications.insert(blank(username, APPROVED, "", "")); return; } - applications.approveUnlessApproved(username, APPROVED, System.currentTimeMillis(), by); + applications.approveUnlessApproved(username, APPROVED, Instant.now(), by); } /// Takes the approval back, when an admin withdraws the DRIVER role. The @@ -447,7 +448,7 @@ public void grant(String by, String username) throws IOException { @Transactional public void withdraw(String by, String username) throws IOException { applications.move(username, APPROVED, REJECTED, "Driving was withdrawn by an admin", - System.currentTimeMillis(), by); + Instant.now(), by); } /// Everything kept about an account's application, for an account being @@ -468,7 +469,7 @@ private void decide(String by, String username, String to, String reason) if (find(username) == null) { throw new ResponseStatusException(404, "No such application"); } - if (applications.move(username, PENDING, to, reason, System.currentTimeMillis(), by) + if (applications.move(username, PENDING, to, reason, Instant.now(), by) != 1) { throw new ResponseStatusException(409, "That application is not waiting for an answer"); } @@ -543,7 +544,7 @@ private DriverApplication editable(String username) { /// moment it was made. private static DriverApplication blank(String username, String status, String vehicle, String plate) { - long now = System.currentTimeMillis(); + Instant now = Instant.now(); DriverApplication application = new DriverApplication(); application.setUsername(username); application.setStatus(status); @@ -552,7 +553,7 @@ private static DriverApplication blank(String username, String status, String ve application.setVehicleSeats(4); application.setProduct(Fares.STANDARD); application.setCreatedAt(now); - application.setReviewedAt(APPROVED.equals(status) ? now : 0L); + application.setReviewedAt(APPROVED.equals(status) ? now : Instant.EPOCH); return application; } @@ -584,7 +585,10 @@ private static DriverApplicationDto toDto(String username, String name, if (KINDS[kind].equals(stored[from])) { status = (String) stored[from + 1]; Object at = stored[from + 2]; - uploadedAt = at instanceof Number ? ((Number) at).longValue() : 0L; + if (!(at instanceof Instant)) { + throw new IllegalStateException("Not a time: " + at); + } + uploadedAt = ((Instant) at).toEpochMilli(); } } listed.add(new DocumentDto(KINDS[kind], status, uploadedAt)); @@ -599,8 +603,8 @@ private static DriverApplicationDto toDto(String username, String name, row.getVehicleMake(), row.getVehicleModel(), row.getVehicleYear(), row.getVehicleColor(), row.getVehiclePlate(), row.getVehicleSeats(), row.getProduct(), row.isWheelchair(), row.isPets(), listed, - row.getRejectionReason(), row.getSubmittedAt(), row.getReviewedAt(), - row.getReviewedBy()); + row.getRejectionReason(), row.getSubmittedAt().toEpochMilli(), + row.getReviewedAt().toEpochMilli(), row.getReviewedBy()); } /// Width and height from a PNG's header chunk, or null without one. diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/live/LiveTickets.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/live/LiveTickets.java index e902411ff0d..f6120900547 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/live/LiveTickets.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/live/LiveTickets.java @@ -28,6 +28,7 @@ import com.codenameone.examples.wayline.repository.LiveTicketRepository; import java.io.IOException; +import java.time.Instant; /// Tickets for the live channel. /// @@ -58,7 +59,7 @@ public TicketDto issue(String username) throws IOException { LiveTicket row = new LiveTicket(); row.setTicketHash(Ids.sha256(ticket)); row.setUsername(username); - row.setExpiresAt(System.currentTimeMillis() + TICKET_SECONDS * 1000L); + row.setExpiresAt(Instant.now().plusSeconds(TICKET_SECONDS)); tickets.insert(row); return new TicketDto(ticket, TICKET_SECONDS); } @@ -78,11 +79,11 @@ public String redeem(String ticket) throws IOException { return null; } String username = row.getUsername(); - long expiresAt = row.getExpiresAt(); + Instant expiresAt = row.getExpiresAt(); // One delete statement: the count it answers is what says this // connection, and not another presenting the same ticket, used it. int removed = tickets.deleteByTicketHash(hash); - if (removed != 1 || expiresAt < System.currentTimeMillis()) { + if (removed != 1 || expiresAt.isBefore(Instant.now())) { return null; } return username; @@ -92,7 +93,7 @@ public String redeem(String ticket) throws IOException { @Scheduled(fixedDelay = 60000, initialDelay = 60000) @Transactional public void sweep() throws IOException { - tickets.deleteByExpiresAtLessThan(System.currentTimeMillis()); + tickets.deleteByExpiresAtLessThan(Instant.now()); } /// Forgets the tickets of an account that is being closed. diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/pay/Payments.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/pay/Payments.java index 04a4b247ab4..629812f11c4 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/pay/Payments.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/pay/Payments.java @@ -45,6 +45,7 @@ import com.codenameone.examples.wayline.repository.RideRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -196,7 +197,7 @@ private String customerForSetup(String username) { /// that are neither finished nor abandoned. private void refuseTooManySetups(String username) { if (setups.countByUsernameAndCompletedFalseAndCreatedAtGreaterThan(username, - System.currentTimeMillis() - SETUP_MILLIS) >= MAX_OPEN_SETUPS) { + Instant.now().minusMillis(SETUP_MILLIS)) >= MAX_OPEN_SETUPS) { throw new ResponseStatusException(429, "Too many cards are being added. Finish one, or try again later"); } @@ -213,7 +214,7 @@ private void refuseTooManySetups(String username) { @Transactional public void sweepSetups() throws IOException { setups.deleteByCompletedTrue(); - setups.deleteByCreatedAtLessThan(System.currentTimeMillis() - 2L * SETUP_MILLIS); + setups.deleteByCreatedAtLessThan(Instant.now().minusMillis(2L * SETUP_MILLIS)); } /// Keeps the reference the processor made for a rider on first use, and @@ -261,7 +262,7 @@ private void keepSetup(String username, String id, String reference) { row.setId(id); row.setUsername(username); row.setReference(reference); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); row.setCompleted(false); setups.insert(row); } @@ -324,7 +325,7 @@ private String[] openSetup(String username, String setupId) { PaymentSetup setup = setupId == null || setupId.length() == 0 || setupId.length() > 32 ? null : setups.findFirstByIdAndUsername(setupId, username); if (setup == null || setup.isCompleted() - || setup.getCreatedAt() < System.currentTimeMillis() - SETUP_MILLIS) { + || setup.getCreatedAt().isBefore(Instant.now().minusMillis(SETUP_MILLIS))) { throw new ResponseStatusException(404, "No such card setup"); } PaymentCustomer customer = customers.findById(username); @@ -353,8 +354,8 @@ private PaymentMethodDto keepCard(String username, String setupId, String id, // Cards are listed in the order they were added, and two added in the // same millisecond would have no order: the later is stamped after // the one before it. - Long newest = cards.newestAt(username); - long after = newest == null ? 0L : newest.longValue() + 1L; + Instant newest = cards.newestAt(username); + Instant now = Instant.now(); PaymentMethod row = new PaymentMethod(); row.setId(id); row.setUsername(username); @@ -364,7 +365,7 @@ private PaymentMethodDto keepCard(String username, String setupId, String id, row.setExpYear(card.expYear); row.setToken(card.token); row.setPreferred(first); - row.setCreatedAt(Math.max(System.currentTimeMillis(), after)); + row.setCreatedAt(newest != null && !newest.isBefore(now) ? newest.plusMillis(1L) : now); cards.insert(row); return card(row); } @@ -491,8 +492,8 @@ public void forget(String username) throws IOException { } } - private static long retriedSince() { - return System.currentTimeMillis() - RETRY_MILLIS; + private static Instant retriedSince() { + return Instant.now().minusMillis(RETRY_MILLIS); } // --------------------------------------------------------------- charges @@ -556,7 +557,7 @@ private void keepPayment(String rideId, long amount, String currency, String sta row.setCurrency(currency); row.setStatus(status); row.setProviderRef(reference); - row.setCreatedAt(System.currentTimeMillis()); + row.setCreatedAt(Instant.now()); payments.insert(row); } @@ -750,7 +751,7 @@ private List refundsPending() { @Transactional private Ride endRefund(String rideId, String outcome) { if (payments.endRefund(rideId, outcome, - REFUNDED.equals(outcome) ? System.currentTimeMillis() : 0L) != 1) { + REFUNDED.equals(outcome) ? Instant.now() : Instant.EPOCH) != 1) { return null; } rides.paymentStatus(rideId, outcome); @@ -872,7 +873,7 @@ private void keepRefund(String rideId, PaymentProvider.Refund fare, payment.setRefundRef(cut(fare.reference, 64)); payment.setTipRefundRef(tip == null ? "" : cut(tip.reference, 64)); payment.setRefundReason(reason); - payment.setRefundedAt(pending ? 0L : System.currentTimeMillis()); + payment.setRefundedAt(pending ? Instant.EPOCH : Instant.now()); } /// Records a refund of the fare whose tip could not be refunded: the ride @@ -885,7 +886,7 @@ private void keepPartialRefund(String rideId, PaymentProvider.Refund fare, Strin payment.setRefundRef(cut(fare.reference, 64)); payment.setTipRefundRef(""); payment.setRefundReason(reason); - payment.setRefundedAt(0L); + payment.setRefundedAt(Instant.EPOCH); } // -------------------------------------------------------------- receipts @@ -917,7 +918,7 @@ public ReceiptDto receipt(String viewer, boolean admin, String rideId) throws IO throw new ResponseStatusException(404, "No such receipt"); } Payment payment = payments.findById(rideId); - return receipt(ride, payment == null ? 0L : payment.getCreatedAt(), admin, + return receipt(ride, payment == null ? 0L : payment.getCreatedAt().toEpochMilli(), admin, new HashMap()); } @@ -934,7 +935,8 @@ private List receipts(List completed, boolean admin) { List rows = payments.findByRideIdIn(ids); for (int iter = 0; iter < rows.size(); iter++) { Payment payment = rows.get(iter); - paidAt.put(payment.getRideId(), Long.valueOf(payment.getCreatedAt())); + paidAt.put(payment.getRideId(), + Long.valueOf(payment.getCreatedAt().toEpochMilli())); } } Map drivers = new HashMap(); @@ -1097,7 +1099,7 @@ private PaymentMethod card(String username, String id) { /// A card tip left unknown counts too, with no time limit: see [#tip]. /// Its retry charges the ride's card under the same key, so with the card /// gone a tip that may have been charged would be cleared as refused. - private boolean awaitsCharge(String rider, String methodId, long since) { + private boolean awaitsCharge(String rider, String methodId, Instant since) { List tipped = rides.findByRiderAndPaymentStatusAndTipCentsGreaterThan(rider, PAID, 0L); for (Ride ride : tipped) { diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/push/PushDevices.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/push/PushDevices.java index 37fe75b134b..2acda4d33fe 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/push/PushDevices.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/push/PushDevices.java @@ -30,6 +30,7 @@ import com.codenameone.examples.wayline.repository.PushDeviceRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -59,7 +60,7 @@ public PushDevices(PushDeviceRepository devices, ProfileRepository profiles) { public PushDeviceDto register(String username, PushDeviceDto device) throws IOException { PushTarget target = target(device); String id = key(target); - long now = System.currentTimeMillis(); + Instant now = Instant.now(); // Before anything is read, the account's profile row is held: a no-op // update that answers 0 when the profile is gone and otherwise keeps // the row locked until this commits. It settles two races. @@ -110,7 +111,7 @@ private void makeRoom(String username) { while (held.size() >= MAX_PER_ACCOUNT) { PushDevice oldest = held.get(0); for (PushDevice each : held) { - if (each.getUpdatedAt() < oldest.getUpdatedAt()) { + if (each.getUpdatedAt().isBefore(oldest.getUpdatedAt())) { oldest = each; } } @@ -146,7 +147,7 @@ List targetsOf(String username) { } // end::wayline-push-devices[] - private static void fill(PushDevice row, String username, PushDeviceDto device, long now) { + private static void fill(PushDevice row, String username, PushDeviceDto device, Instant now) { row.setUsername(username); row.setPlatform(Text.optional(device.platform(), 32, "the platform")); row.setUpdatedAt(now); diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/push/RidePushes.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/push/RidePushes.java index a1a6788db68..4ebcb84a229 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/push/RidePushes.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/push/RidePushes.java @@ -43,6 +43,7 @@ import com.codenameone.examples.wayline.ride.Rides; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -151,9 +152,9 @@ public void rideChanged(String id, RideState state, String rider, String driver) /// end that failed again is reported once the rest have been tried. @Scheduled(fixedDelay = 60000, initialDelay = 50000, lock = "wayline-activity-ends") public void endLeftBehind() throws IOException { - long now = System.currentTimeMillis(); - dropEndedBefore(now - END_RETRY_MILLIS); - List left = leftBehind(now - END_GRACE_MILLIS); + Instant now = Instant.now(); + dropEndedBefore(now.minusMillis(END_RETRY_MILLIS)); + List left = leftBehind(now.minusMillis(END_GRACE_MILLIS)); Exception failed = null; for (int iter = 0; iter < left.size(); iter++) { String id = left.get(iter).getRideId(); @@ -174,13 +175,13 @@ public void endLeftBehind() throws IOException { } @Transactional - private void dropEndedBefore(long before) { - activities.dropEndedBefore(before); + private void dropEndedBefore(Instant before) { + activities.dropEndedBefore(before, Instant.EPOCH); } @Transactional(readOnly = true) - private List leftBehind(long before) { - return activities.leftBehind(before, new PageRequest(0, 50)); + private List leftBehind(Instant before) { + return activities.leftBehind(before, Instant.EPOCH, new PageRequest(0, 50)); } @Transactional @@ -252,11 +253,11 @@ public RideActivityDto attach(String rider, String rideId, RideActivityDto activ row.setRideId(rideId); row.setUsername(rider); row.setActivityId(activityId); - row.setSentAt(System.currentTimeMillis()); + row.setSentAt(Instant.now()); activities.insert(row); } else { row.setActivityId(activityId); - row.setSentAt(System.currentTimeMillis()); + row.setSentAt(Instant.now()); } return new RideActivityDto(activityId); } @@ -376,7 +377,7 @@ private List compose(String id, RideState state, String rider, String } // end::wayline-push-messages[] if (!state.isActive() && activity != null) { - activities.markEnded(id, System.currentTimeMillis()); + activities.markEnded(id, Instant.now(), Instant.EPOCH); } if (toRider != null && !wants(rider, RideState.COMPLETED == state)) { toRider = null; @@ -423,10 +424,10 @@ private List moved(String rideId, double lat, double lng) throws IOExc if (activity == null) { return out; } - long now = System.currentTimeMillis(); + Instant now = Instant.now(); // A conditional update, so that two reports arriving together send one // update between them. - if (activities.claim(rideId, now, now - activityMillis) != 1) { + if (activities.claim(rideId, now, now.minusMillis(activityMillis)) != 1) { return out; } Ride ride = rides.findById(rideId); diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/DriverApplicationRepository.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/DriverApplicationRepository.java index 45aea747af3..3d4b5e02329 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/DriverApplicationRepository.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/DriverApplicationRepository.java @@ -26,6 +26,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.wayline.domain.DriverApplication; +import java.time.Instant; import java.util.List; /// Applications to drive, one per account at most, keyed by the account. @@ -72,7 +73,7 @@ public interface DriverApplicationRepository extends CrudRepository :to") int approveUnlessApproved(@Param("username") String username, - @Param("to") String approved, @Param("at") long at, @Param("by") String by); + @Param("to") String approved, @Param("at") Instant at, @Param("by") String by); /// Hands an application in: from the status it was read in to `to`, with /// the last rejection's reason cleared. @@ -89,7 +90,7 @@ int approveUnlessApproved(@Param("username") String username, @Query("update DriverApplication a set a.status = :to, a.submittedAt = :at, " + "a.rejectionReason = '' where a.username = :username and a.status = :from") int submit(@Param("username") String username, @Param("from") String from, - @Param("to") String to, @Param("at") long at); + @Param("to") String to, @Param("at") Instant at); /// Makes the rest of the transaction wait its turn behind any other that /// holds, or moves, the same application. diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/DriverDocumentRepository.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/DriverDocumentRepository.java index 63015ad1e33..535816440bd 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/DriverDocumentRepository.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/DriverDocumentRepository.java @@ -26,6 +26,7 @@ import com.codename1.orm.session.Identifier; import com.codenameone.examples.wayline.domain.DriverDocument; +import java.time.Instant; import java.util.List; /// The documents of applications to drive, keyed by @@ -58,7 +59,7 @@ public interface DriverDocumentRepository extends CrudRepository freeInBox(@Param("fresh") long fresh, @Param("south") double south, + List freeInBox(@Param("fresh") Instant fresh, @Param("south") double south, @Param("north") double north, @Param("west") double west, @Param("east") double east, @Param("approved") String approved, @Param("withRide") RideState[] withRide); @@ -85,7 +86,7 @@ List freeInBox(@Param("fresh") long fresh, @Param("south") double s int takeOffLine(@Param("username") String username); /// The drivers on line who reported in at or after `seenSince`. - long countByOnlineTrueAndLastSeenGreaterThanEqual(long seenSince); + long countByOnlineTrueAndLastSeenGreaterThanEqual(Instant seenSince); int deleteByUsername(String username); } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/LiveTicketRepository.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/LiveTicketRepository.java index 1b84547ab97..44ae5c711de 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/LiveTicketRepository.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/LiveTicketRepository.java @@ -21,6 +21,7 @@ import com.codename1.orm.repository.CrudRepository; import com.codename1.orm.repository.Repository; import com.codenameone.examples.wayline.domain.LiveTicket; +import java.time.Instant; /// The tickets that open a live connection. Only the hash of a ticket is /// stored, and it is the row's key. @@ -33,7 +34,7 @@ public interface LiveTicketRepository extends CrudRepository int deleteByTicketHash(String ticketHash); /// Deletes the tickets that went stale before `now`. - int deleteByExpiresAtLessThan(long now); + int deleteByExpiresAtLessThan(Instant now); int deleteByUsername(String username); } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/ModerationEventRepository.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/ModerationEventRepository.java index 680e8f19138..a7fbfe21c57 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/ModerationEventRepository.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/ModerationEventRepository.java @@ -24,6 +24,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.wayline.domain.ModerationEvent; +import java.time.Instant; import java.util.List; /// The record of what the admins did to each account. @@ -32,7 +33,7 @@ public interface ModerationEventRepository extends CrudRepository findTop100ByUsernameOrderByCreatedAtDescIdAsc(String username); diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/PaymentMethodRepository.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/PaymentMethodRepository.java index 01b1646738e..7b1b104e8cb 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/PaymentMethodRepository.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/PaymentMethodRepository.java @@ -24,6 +24,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.wayline.domain.PaymentMethod; +import java.time.Instant; import java.util.List; /// The cards accounts saved. @@ -42,7 +43,7 @@ public interface PaymentMethodRepository extends CrudRepository { @Query("update Payment p set p.status = :status, p.refundedAt = :at " + "where p.rideId = :id and p.status = 'REFUND_PENDING'") int endRefund(@Param("id") String rideId, @Param("status") String status, - @Param("at") long at); + @Param("at") Instant at); } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/PaymentSetupRepository.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/PaymentSetupRepository.java index e81e7c95c63..a5feb7268e4 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/PaymentSetupRepository.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/PaymentSetupRepository.java @@ -24,6 +24,7 @@ import com.codename1.orm.repository.Query; import com.codename1.orm.repository.Repository; import com.codenameone.examples.wayline.domain.PaymentSetup; +import java.time.Instant; /// The card setups accounts began with the payment processor. @Repository(entity = PaymentSetup.class, key = String.class) @@ -39,7 +40,7 @@ public interface PaymentSetupRepository extends CrudRepository { /// When each account made since `since` was made. @Query("select p.createdAt from Profile p where p.createdAt >= :since") - List signUps(@Param("since") long since); + List signUps(@Param("since") Instant since); } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideActivityRepository.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideActivityRepository.java index 5e0a7c64c84..efe7ae4c33a 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideActivityRepository.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideActivityRepository.java @@ -26,6 +26,7 @@ import com.codename1.orm.repository.Repository; import com.codenameone.examples.wayline.domain.RideActivity; +import java.time.Instant; import java.util.List; /// The Live Activities riders follow their rides in, by ride. @@ -40,23 +41,26 @@ public interface RideActivityRepository extends CrudRepository 0 and a.endedAt < :before " + @Query("select a from RideActivity a where a.endedAt > :none and a.endedAt < :before " + "order by a.endedAt") - List leftBehind(@Param("before") long before, PageRequest page); + List leftBehind(@Param("before") Instant before, @Param("none") Instant none, + PageRequest page); /// Forgets the activities whose ride ended before `before`. @Modifying - @Query("delete from RideActivity a where a.endedAt > 0 and a.endedAt < :before") - int dropEndedBefore(@Param("before") long before); + @Query("delete from RideActivity a where a.endedAt > :none and a.endedAt < :before") + int dropEndedBefore(@Param("before") Instant before, @Param("none") Instant none); } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideEventRepository.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideEventRepository.java index dc9ca139a6f..9baef41d178 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideEventRepository.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideEventRepository.java @@ -25,6 +25,7 @@ import com.codenameone.examples.wayline.api.RideState; import com.codenameone.examples.wayline.domain.RideEvent; +import java.time.Instant; import java.util.List; /// What happened to each ride: one row for every state it came into. @@ -42,5 +43,5 @@ public interface RideEventRepository extends CrudRepository { /// rides are named by a nested query. @Query("select e.rideId, e.createdAt from RideEvent e where e.state = :state " + "and e.rideId in (select r.id from Ride r where r.requestedAt >= :since)") - List reached(@Param("since") long since, @Param("state") RideState state); + List reached(@Param("since") Instant since, @Param("state") RideState state); } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideRepository.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideRepository.java index 19e7a1fce90..411bfa8fcac 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideRepository.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/repository/RideRepository.java @@ -27,6 +27,7 @@ import com.codenameone.examples.wayline.api.RideState; import com.codenameone.examples.wayline.domain.Ride; +import java.time.Instant; import java.util.List; /// Rides. @@ -70,11 +71,11 @@ boolean existsByRiderAndMethodIdAndStateIn(String rider, String methodId, /// `paymentStatus` and which ended after `since`, is to be charged to /// this method. boolean existsByRiderAndStateAndPaymentStatusAndUpdatedAtGreaterThanAndMethodId( - String rider, RideState state, String paymentStatus, long since, String methodId); + String rider, RideState state, String paymentStatus, Instant since, String methodId); /// The same, to be charged to any method but `methodId`. boolean existsByRiderAndStateAndPaymentStatusAndUpdatedAtGreaterThanAndMethodIdNot( - String rider, RideState state, String paymentStatus, long since, String methodId); + String rider, RideState state, String paymentStatus, Instant since, String methodId); /// A rider's rides whose payment is `paymentStatus` and that carry a tip. List findByRiderAndPaymentStatusAndTipCentsGreaterThan(String rider, @@ -99,18 +100,18 @@ List findByRiderAndStateOrderByRequestedAtDesc(String rider, RideState sta List newest(PageRequest page); /// The rides in `state` whose offer ran out before `now`. - List findByStateAndOfferExpiresAtLessThan(RideState state, long now); + List findByStateAndOfferExpiresAtLessThan(RideState state, Instant now); /// The rides in `state`, the one that has waited longest first. List findByStateOrderByRequestedAtAsc(RideState state); /// A driver's rides in `state` that changed at or after a time. List findByDriverAndStateAndUpdatedAtGreaterThanEqual(String driver, - RideState state, long since); + RideState state, Instant since); long countByDriverAndState(String driver, RideState state); - long countByRequestedAtGreaterThanEqual(long since); + long countByRequestedAtGreaterThanEqual(Instant since); long countByStateIn(RideState[] states); @@ -128,14 +129,14 @@ long countByRiderAndStateOrDriverAndState(String rider, RideState asRider, Strin @Query("update Ride r set r.state = :to, r.updatedAt = :now " + "where r.id = :id and r.state in :from and r.rider = :rider") int moveAsRider(@Param("id") String id, @Param("from") RideState[] from, - @Param("to") RideState to, @Param("now") long now, @Param("rider") String rider); + @Param("to") RideState to, @Param("now") Instant now, @Param("rider") String rider); /// Moves a ride of `driver`'s from one of `from` to `to`. @Modifying(clearAutomatically = true) @Query("update Ride r set r.state = :to, r.updatedAt = :now " + "where r.id = :id and r.state in :from and r.driver = :driver") int moveAsDriver(@Param("id") String id, @Param("from") RideState[] from, - @Param("to") RideState to, @Param("now") long now, @Param("driver") String driver); + @Param("to") RideState to, @Param("now") Instant now, @Param("driver") String driver); // tag::wayline-ride-move[] /// Takes an offer made to `driver`: refused once the offer has lapsed, as @@ -145,7 +146,7 @@ int moveAsDriver(@Param("id") String id, @Param("from") RideState[] from, + "where r.id = :id and r.state in :from and r.driver = :driver " + "and r.offerExpiresAt >= :now") int takeOffer(@Param("id") String id, @Param("from") RideState[] from, - @Param("to") RideState to, @Param("now") long now, @Param("driver") String driver); + @Param("to") RideState to, @Param("now") Instant now, @Param("driver") String driver); // end::wayline-ride-move[] /// Gives a ride of `driver`'s back to be offered again, writing @@ -154,7 +155,7 @@ int takeOffer(@Param("id") String id, @Param("from") RideState[] from, @Query("update Ride r set r.state = :to, r.updatedAt = :now, r.driver = :newDriver " + "where r.id = :id and r.state in :from and r.driver = :driver") int giveBack(@Param("id") String id, @Param("from") RideState[] from, - @Param("to") RideState to, @Param("now") long now, @Param("driver") String driver, + @Param("to") RideState to, @Param("now") Instant now, @Param("driver") String driver, @Param("newDriver") String newDriver); /// Holds `rider`'s ride while it is in one of `states`, answering 0 when @@ -174,15 +175,15 @@ int holdWhile(@Param("id") String id, @Param("rider") String rider, @Query("update Ride r set r.state = :to, r.updatedAt = :now " + "where r.id = :id and r.state in :from") int moveByServer(@Param("id") String id, @Param("from") RideState[] from, - @Param("to") RideState to, @Param("now") long now); + @Param("to") RideState to, @Param("now") Instant now); /// Offers a ride to `driver` until `expiresAt`. @Modifying(clearAutomatically = true) @Query("update Ride r set r.state = :to, r.updatedAt = :now, r.driver = :driver, " + "r.offerExpiresAt = :expiresAt where r.id = :id and r.state in :from") int offer(@Param("id") String id, @Param("from") RideState[] from, - @Param("to") RideState to, @Param("now") long now, @Param("driver") String driver, - @Param("expiresAt") long expiresAt); + @Param("to") RideState to, @Param("now") Instant now, @Param("driver") String driver, + @Param("expiresAt") Instant expiresAt); // ----------------------------------------------------------- the rest @@ -200,7 +201,7 @@ int offer(@Param("id") String id, @Param("from") RideState[] from, /// behind the new arrivals until they aged out of the window unsettled. @Query("select r from Ride r where r.state = 'COMPLETED' and r.paymentStatus = 'PENDING' " + "and r.updatedAt < :before and r.updatedAt > :after order by r.updatedAt asc") - List unsettled(@Param("after") long after, @Param("before") long before, + List unsettled(@Param("after") Instant after, @Param("before") Instant before, PageRequest page); /// Records how the charge for a ride came out. A statement of its own and @@ -262,13 +263,13 @@ List unsettled(@Param("after") long after, @Param("before") long before, @Query("select count(r), coalesce(sum(r.driverCents), 0) from Ride r " + "where r.driver = :driver and r.state = 'COMPLETED' and r.paymentStatus = 'PAID' " + "and r.updatedAt >= :since") - Object[] paidTotalsSince(@Param("driver") String driver, @Param("since") long since); + Object[] paidTotalsSince(@Param("driver") String driver, @Param("since") Instant since); /// What the driver's share of their completed, paid rides came to since /// a time. @Query("select coalesce(sum(r.driverCents), 0) from Ride r where r.driver = :driver " + "and r.state = 'COMPLETED' and r.paymentStatus = 'PAID' and r.updatedAt >= :since") - Long paidSince(@Param("driver") String driver, @Param("since") long since); + Long paidSince(@Param("driver") String driver, @Param("since") Instant since); /// The driver's share of the fares of every ride they completed and that /// was paid for -- in cash, or by a card whose charge came back. A charge @@ -295,7 +296,7 @@ List unsettled(@Param("after") long after, @Param("before") long before, @Query("select r.id from Ride r where r.driver = :driver and r.state = 'COMPLETED' " + "and r.updatedAt >= :since and r.methodId <> 'cash' and r.paymentStatus = 'PAID' " + "and r.id in (select p.rideId from Payment p where p.tipRef <> '')") - List tipChargedSince(@Param("driver") String driver, @Param("since") long since); + List tipChargedSince(@Param("driver") String driver, @Param("since") Instant since); /// What riders paid in fares for rides in `state` whose payment is `paid`. @Query("select coalesce(sum(r.fareCents), 0) from Ride r " @@ -305,22 +306,22 @@ List unsettled(@Param("after") long after, @Param("before") long before, /// The fares of the rides in `state` asked for since `since`, paid or not. @Query("select coalesce(sum(r.fareCents), 0) from Ride r " + "where r.requestedAt >= :since and r.state = :state") - Long faresSince(@Param("since") long since, @Param("state") RideState state); + Long faresSince(@Param("since") Instant since, @Param("state") RideState state); /// The rides asked for since `since`, counted by state: `{state, count}`. @Query("select r.state, count(r) from Ride r where r.requestedAt >= :since group by r.state") - List countByState(@Param("since") long since); + List countByState(@Param("since") Instant since); /// The same by product: `{product, count}`. @Query("select r.product, count(r) from Ride r where r.requestedAt >= :since " + "group by r.product") - List countByProduct(@Param("since") long since); + List countByProduct(@Param("since") Instant since); /// The rides in `state` asked for since `since`, counted by driver: /// `{driver, count}`. @Query("select r.driver, count(r) from Ride r where r.requestedAt >= :since " + "and r.state = :state group by r.driver") - List countByDriver(@Param("since") long since, @Param("state") RideState state); + List countByDriver(@Param("since") Instant since, @Param("state") RideState state); /// One row for each ride asked for since `since`: `{id, requestedAt, /// state, fareCents, paymentStatus}`. @@ -333,7 +334,7 @@ List unsettled(@Param("after") long after, @Param("before") long before, /// word does not see those as one expression. @Query("select r.id, r.requestedAt, r.state, r.fareCents, r.paymentStatus from Ride r " + "where r.requestedAt >= :since") - List timeline(@Param("since") long since); + List timeline(@Param("since") Instant since); /// What a rider paid for rides in `state` whose payment is `paid`: /// `{fares, fees, tips}`. diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/DemoRides.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/DemoRides.java index 5c4e79d5bf5..5823d2f2173 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/DemoRides.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/DemoRides.java @@ -44,6 +44,7 @@ import com.codenameone.examples.wayline.repository.RideRepository; import java.io.IOException; +import java.time.Instant; /// Two weeks of rides that were never taken, so that the admin's charts, a /// driver's earnings and a rider's receipts have something in them the first @@ -180,9 +181,9 @@ public void seed(String[] riders, String[] drivers, boolean untilToday) throws I ride.setCurrency(fares.currency()); ride.setDistanceMeters(meters); ride.setDurationSeconds(seconds); - ride.setRequestedAt(at); - ride.setUpdatedAt(ended); - ride.setSearchUntil(at + 90000L); + ride.setRequestedAt(Instant.ofEpochMilli(at)); + ride.setUpdatedAt(Instant.ofEpochMilli(ended)); + ride.setSearchUntil(Instant.ofEpochMilli(at + 90000L)); ride.setStars(given); ride.setPaymentStatus(completed ? Payments.PAID : Payments.PENDING); ride.setProduct(products[driverIndex]); @@ -222,7 +223,7 @@ public void seed(String[] riders, String[] drivers, boolean untilToday) throws I // and for a refund -- once its charge has a reference. payment.setTipRef("sim_ch_tip-" + id); } - payment.setCreatedAt(ended); + payment.setCreatedAt(Instant.ofEpochMilli(ended)); paid.insert(payment); lastSeen[driverIndex] = Math.max(lastSeen[driverIndex], ended); if (ended < now - 7L * Days.MILLIS) { @@ -246,7 +247,7 @@ public void seed(String[] riders, String[] drivers, boolean untilToday) throws I } car.setLat(real(iter % PLACES.length, 1)); car.setLng(real(iter % PLACES.length, 2)); - car.setLastSeen(lastSeen[iter]); + car.setLastSeen(Instant.ofEpochMilli(lastSeen[iter])); car.setRatingSum(stars[iter]); car.setRatingCount(rated[iter]); if (first) { @@ -265,7 +266,7 @@ public void seed(String[] riders, String[] drivers, boolean untilToday) throws I payout.setDriver(drivers[iter]); payout.setAmountCents(earnedEarlier[iter]); payout.setStatus("paid"); - payout.setCreatedAt(now - 7L * Days.MILLIS); + payout.setCreatedAt(Instant.ofEpochMilli(now - 7L * Days.MILLIS)); payout.setDestination("Bay Credit Union ****67" + (10 + iter)); payouts.insert(payout); } @@ -278,7 +279,7 @@ private void event(String ride, RideState state, String actor, long at) throws I event.setRideId(ride); event.setState(state); event.setActor(actor); - event.setCreatedAt(at); + event.setCreatedAt(Instant.ofEpochMilli(at)); events.insert(event); } diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Fares.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Fares.java index b578c1a7f0e..55275fbc8b2 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Fares.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Fares.java @@ -30,6 +30,7 @@ import com.codenameone.examples.wayline.repository.PricingRepository; import java.io.IOException; +import java.time.Instant; /// What a ride costs. /// @@ -88,7 +89,7 @@ public PricingDto pricing() throws IOException { private PricingDto toDto(Pricing row) { // The row a migration created and nobody has saved over yet. - if (row == null || row.getUpdatedAt() == 0L) { + if (row == null || Instant.EPOCH.equals(row.getUpdatedAt())) { return defaults; } // The currency is a setting and stays one. Rides already taken are in @@ -121,7 +122,7 @@ public PricingDto save(String by, PricingDto wanted) throws IOException { if (prices.change(PricingRepository.ONLY.intValue(), wanted.baseFare(), wanted.perKm(), wanted.perMinute(), wanted.minimumFare(), wanted.serviceFeePercent(), wanted.commissionPercent(), wanted.surgeMultiplier(), - wanted.comfortMultiplier(), wanted.xlMultiplier(), System.currentTimeMillis(), + wanted.comfortMultiplier(), wanted.xlMultiplier(), Instant.now(), by) == 0) { throw new IllegalStateException("The pricing row is missing; the V6 migration " + "creates it"); diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Matcher.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Matcher.java index 4363ef2078f..a243eca7bca 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Matcher.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Matcher.java @@ -36,6 +36,7 @@ import com.codenameone.examples.wayline.repository.RidePassedRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -145,7 +146,7 @@ public List nearby(double lat, double lng, double radiusMeters, Strin double dLat = radiusMeters / Geo.METERS_PER_DEGREE; double shrink = Math.max(0.01d, Math.cos(Math.toRadians(lat))); double dLng = radiusMeters / (Geo.METERS_PER_DEGREE * shrink); - List boxed = drivers.freeInBox(System.currentTimeMillis() - FRESH_MILLIS, + List boxed = drivers.freeInBox(Instant.now().minusMillis(FRESH_MILLIS), lat - dLat, lat + dLat, lng - dLng, lng + dLng, Applications.APPROVED, WITH_RIDE); List inReach = new ArrayList(); List names = new ArrayList(); diff --git a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Rides.java b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Rides.java index 8bc4db9443a..52570aac5f6 100644 --- a/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Rides.java +++ b/scripts/wayline/backend/src/main/java/com/codenameone/examples/wayline/ride/Rides.java @@ -53,6 +53,7 @@ import com.codenameone.examples.wayline.repository.RideRepository; import java.io.IOException; +import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -234,7 +235,7 @@ private String open(String rider, RideRequestDto request) throws IOException { double seconds = fares.durationSeconds(request, meters); PricingDto pricing = fares.pricing(); Fares.Price price = Fares.price(pricing, meters, seconds, product); - long now = System.currentTimeMillis(); + Instant now = Instant.now(); // The fare is fixed here, from the server's own arithmetic, and so is // the driver's share of it: a change of prices or of commission made // while the ride is under way is for the rides after it. The quote the @@ -255,7 +256,7 @@ private String open(String rider, RideRequestDto request) throws IOException { ride.setDurationSeconds(seconds); ride.setRequestedAt(now); ride.setUpdatedAt(now); - ride.setSearchUntil(now + searchMillis); + ride.setSearchUntil(now.plusMillis(searchMillis)); ride.setPaymentStatus(Payments.PENDING); ride.setProduct(product); ride.setMethodId(method[0]); @@ -412,8 +413,9 @@ private Ride finish(String driver, String id) throws IOException { /// became of such a ride is for a person to find in the processor's records. @Scheduled(fixedDelay = 60000, initialDelay = 30000, lock = "wayline-settlement") public void settleLeftBehind() throws IOException { - long now = System.currentTimeMillis(); - List unsettled = unsettled(now - RETRY_MILLIS, now - UNSETTLED_MILLIS); + Instant now = Instant.now(); + List unsettled = unsettled(now.minusMillis(RETRY_MILLIS), + now.minusMillis(UNSETTLED_MILLIS)); Exception failed = null; for (int iter = 0; iter < unsettled.size(); iter++) { Ride ride = unsettled.get(iter); @@ -434,7 +436,7 @@ public void settleLeftBehind() throws IOException { } @Transactional(readOnly = true) - private List unsettled(long after, long before) { + private List unsettled(Instant after, Instant before) { return rides.unsettled(after, before, new PageRequest(0, 50)); } @@ -568,12 +570,12 @@ private Change choose(String id, String[] chosen) throws IOException { if (ride == null || RideState.REQUESTED != ride.getState()) { return null; } - long now = System.currentTimeMillis(); - if (now > ride.getSearchUntil()) { + Instant now = Instant.now(); + if (now.isAfter(ride.getSearchUntil())) { return tryMove(id, RideState.NO_DRIVERS, "", null, null, null) ? new Change(id, RideState.NO_DRIVERS, ride.getRider(), "", "", null) : null; } - chosen[0] = matcher.pick(ride, now - ride.getRequestedAt()); + chosen[0] = matcher.pick(ride, now.toEpochMilli() - ride.getRequestedAt().toEpochMilli()); return null; } @@ -603,11 +605,12 @@ Change offer(String id, String driver) throws IOException { if (ride == null || RideState.REQUESTED != ride.getState()) { return null; } - long now = System.currentTimeMillis(); - if (!matcher.fits(ride, driver, now - ride.getRequestedAt())) { + Instant now = Instant.now(); + if (!matcher.fits(ride, driver, + now.toEpochMilli() - ride.getRequestedAt().toEpochMilli())) { return null; } - return tryMove(id, RideState.OFFERED, "", null, driver, Long.valueOf(now + offerMillis)) + return tryMove(id, RideState.OFFERED, "", null, driver, now.plusMillis(offerMillis)) ? new Change(id, RideState.OFFERED, ride.getRider(), driver, "", null) : null; } // end::wayline-ride-offer[] @@ -622,7 +625,7 @@ Change offer(String id, String driver) throws IOException { @Scheduled(fixedDelay = 2000, initialDelay = 2000, lock = "wayline-matching") public void tick() throws IOException { Exception failed = null; - List lapsed = lapsedOffers(System.currentTimeMillis()); + List lapsed = lapsedOffers(Instant.now()); for (int iter = 0; iter < lapsed.size(); iter++) { Ride ride = lapsed.get(iter); try { @@ -652,7 +655,7 @@ public void tick() throws IOException { } @Transactional(readOnly = true) - private List lapsedOffers(long now) throws IOException { + private List lapsedOffers(Instant now) throws IOException { return rides.findByStateAndOfferExpiresAtLessThan(RideState.OFFERED, now); } @@ -758,7 +761,7 @@ private static T attempt(Work work) throws IOException { /// Moves a ride to `to`, or answers 409 when its state does not allow it. private void move(String id, RideState to, String actor, String ownerField, String newDriver, - Long newOfferExpiresAt) throws IOException { + Instant newOfferExpiresAt) throws IOException { if (!tryMove(id, to, actor, ownerField, newDriver, newOfferExpiresAt)) { Ride now = find(id); throw new ResponseStatusException(409, "That ride is " @@ -781,15 +784,15 @@ private void move(String id, RideState to, String actor, String ownerField, Stri /// @param newOfferExpiresAt when the offer this change makes lapses, or null // tag::wayline-ride-trymove[] private boolean tryMove(String id, RideState to, String actor, String ownerField, - String newDriver, Long newOfferExpiresAt) throws IOException { + String newDriver, Instant newOfferExpiresAt) throws IOException { RideState[] sources = RideStateMachine.sources(to); if (sources.length == 0) { return false; } - long now = System.currentTimeMillis(); + Instant now = Instant.now(); int moved; if (newOfferExpiresAt != null) { - moved = rides.offer(id, sources, to, now, newDriver, newOfferExpiresAt.longValue()); + moved = rides.offer(id, sources, to, now, newDriver, newOfferExpiresAt); } else if (RIDER.equals(ownerField)) { moved = rides.moveAsRider(id, sources, to, now, actor); } else if (!DRIVER.equals(ownerField)) { @@ -817,7 +820,7 @@ private void event(String id, RideState state, String actor) throws IOException event.setRideId(id); event.setState(state); event.setActor(actor); - event.setCreatedAt(System.currentTimeMillis()); + event.setCreatedAt(Instant.now()); events.insert(event); } @@ -957,7 +960,7 @@ private RideDto toDto(Ride ride, String viewer, Map cache, bool } if (offered) { offerExpiresInSeconds = (int) Math.max(0L, - (ride.getOfferExpiresAt() - System.currentTimeMillis()) / 1000L); + (ride.getOfferExpiresAt().toEpochMilli() - System.currentTimeMillis()) / 1000L); } long fareCents = ride.getFareCents(); long serviceFee = ride.getFeeCents(); @@ -985,8 +988,8 @@ private RideDto toDto(Ride ride, String viewer, Map cache, bool ride.getCurrency(), ride.getDistanceMeters(), ride.getDurationSeconds(), - ride.getRequestedAt(), - ride.getUpdatedAt(), + ride.getRequestedAt().toEpochMilli(), + ride.getUpdatedAt().toEpochMilli(), ride.getStars(), ride.getPaymentStatus(), offerExpiresInSeconds,