From e5353e420e262094dc74518b9142a264ddfba506 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 24 Oct 2026 05:11:13 +0300 Subject: [PATCH 1/8] ORM: map java.time Instant, LocalDate and LocalDateTime fields Without an annotation they take Date's portable default, a number in an integer column (epoch millis, or epoch days for a LocalDate), so an Instant reads what a long or a Date of milliseconds wrote. @Temporal opts them into native TIMESTAMP/DATE columns through TemporalConverter's UTC ISO text. Co-Authored-By: Claude Opus 5.5 --- .../codename1/annotations/db/Temporal.java | 8 +- .../codename1/impl/orm/JavaTimeConverter.java | 163 ++++++++++++++++++ .../Annotation-SQLite-ORM.asciidoc | 27 ++- .../processors/OrmAnnotationProcessor.java | 34 +++- .../OrmAnnotationProcessorTest.java | 60 ++++++- 5 files changed, 283 insertions(+), 9 deletions(-) create mode 100644 CodenameOne/src/com/codename1/impl/orm/JavaTimeConverter.java diff --git a/CodenameOne/src/com/codename1/annotations/db/Temporal.java b/CodenameOne/src/com/codename1/annotations/db/Temporal.java index cde32975604..a62831b5c7e 100644 --- a/CodenameOne/src/com/codename1/annotations/db/Temporal.java +++ b/CodenameOne/src/com/codename1/annotations/db/Temporal.java @@ -27,8 +27,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -/// Stores a `java.util.Date` field in a native date or timestamp column instead -/// of the portable default, epoch milliseconds in an integer column. +/// Stores a `java.util.Date`, `java.time.Instant`, `LocalDate` or +/// `LocalDateTime` field in a native date or timestamp column instead of the +/// portable default, a number in an integer column: epoch milliseconds, or +/// epoch days for a `LocalDate`. A `LocalDate` takes `DATE` and the other +/// java.time types take `TIMESTAMP`; a `LocalDateTime` is written as its wall +/// clock, with no zone applied. /// /// Opt-in, because the two are different columns: an existing integer column /// keeps its milliseconds and an existing native one needs this annotation. diff --git a/CodenameOne/src/com/codename1/impl/orm/JavaTimeConverter.java b/CodenameOne/src/com/codename1/impl/orm/JavaTimeConverter.java new file mode 100644 index 00000000000..3d102178025 --- /dev/null +++ b/CodenameOne/src/com/codename1/impl/orm/JavaTimeConverter.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2026, Codename One and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Codename One designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Codename One through http://www.codenameone.com/ if you + * need additional information or have any questions. + */ +package com.codename1.impl.orm; + +import com.codename1.orm.session.AttributeConverter; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; + +/// The storage of `java.time.Instant`, `LocalDate` and `LocalDateTime` fields. +/// +/// The defaults follow `java.util.Date`'s: a number in an integer column, which +/// sorts, compares and indexes the same on every engine. An Instant or a +/// LocalDateTime is milliseconds since 1970-01-01T00:00 -- UTC for the Instant, +/// the wall clock itself for the LocalDateTime, which has no zone to convert +/// through -- and a LocalDate is the day count since 1970-01-01. So an Instant +/// reads a column a `long createdAt` or a `Date` wrote, unchanged. +/// +/// `@Temporal` opts into a native column instead, through the same UTC ISO text +/// [TemporalConverter] writes: `TIMESTAMP` for an Instant or a LocalDateTime, +/// `DATE` for a LocalDate. +/// +/// Precision is the millisecond, as for a Date: nanoseconds below it are dropped +/// toward the earlier instant on write. +/// +/// Internal ORM runtime; not an application API. +/// @hidden +@com.codename1.impl.SharedWithBackend +public final class JavaTimeConverter { + private static final long DAY = 86400000L; + + private JavaTimeConverter() { + } + + /// An Instant as epoch milliseconds, the default. + /// @hidden + public static final class InstantMillis implements AttributeConverter { + @Override + public Long toDatabase(Instant value) { + return value == null ? null : Long.valueOf(value.toEpochMilli()); + } + + @Override + public Instant fromDatabase(Long value) { + return value == null ? null : Instant.ofEpochMilli(value.longValue()); + } + } + + /// An Instant in a native timestamp column, `@Temporal(TemporalType.TIMESTAMP)`. + /// @hidden + public static final class InstantTimestamp implements AttributeConverter { + private final TemporalConverter text = new TemporalConverter.Timestamp(); + + @Override + public String toDatabase(Instant value) { + return value == null ? null : text.toDatabase(new java.util.Date(value.toEpochMilli())); + } + + @Override + public Instant fromDatabase(String value) { + return value == null ? null : Instant.ofEpochMilli(TemporalConverter.parse(value)); + } + } + + /// A LocalDate as the day count since 1970-01-01, the default. + /// @hidden + public static final class LocalDateEpochDay implements AttributeConverter { + @Override + public Long toDatabase(LocalDate value) { + return value == null ? null : Long.valueOf(value.toEpochDay()); + } + + @Override + public LocalDate fromDatabase(Long value) { + return value == null ? null : LocalDate.ofEpochDay(value.longValue()); + } + } + + /// A LocalDate in a native date column, `@Temporal(TemporalType.DATE)`. + /// @hidden + public static final class LocalDateDay implements AttributeConverter { + private final TemporalConverter text = new TemporalConverter.Day(); + + @Override + public String toDatabase(LocalDate value) { + return value == null ? null : text.toDatabase(new java.util.Date(value.toEpochDay() * DAY)); + } + + @Override + public LocalDate fromDatabase(String value) { + return value == null ? null : LocalDate.ofEpochDay(floorDiv(TemporalConverter.parse(value), DAY)); + } + } + + /// A LocalDateTime's wall clock as milliseconds since 1970-01-01T00:00, the + /// default. + /// @hidden + public static final class LocalDateTimeMillis implements AttributeConverter { + @Override + public Long toDatabase(LocalDateTime value) { + return value == null ? null : Long.valueOf(millis(value)); + } + + @Override + public LocalDateTime fromDatabase(Long value) { + return value == null ? null : wallClock(value.longValue()); + } + } + + /// A LocalDateTime in a native timestamp column, + /// `@Temporal(TemporalType.TIMESTAMP)`. The wall clock is written as is; the + /// backend's UTC session means no zone ever shifts it. + /// @hidden + public static final class LocalDateTimeTimestamp implements AttributeConverter { + private final TemporalConverter text = new TemporalConverter.Timestamp(); + + @Override + public String toDatabase(LocalDateTime value) { + return value == null ? null : text.toDatabase(new java.util.Date(millis(value))); + } + + @Override + public LocalDateTime fromDatabase(String value) { + return value == null ? null : wallClock(TemporalConverter.parse(value)); + } + } + + static long millis(LocalDateTime value) { + return value.toLocalDate().toEpochDay() * DAY + value.toLocalTime().toNanoOfDay() / 1000000L; + } + + static LocalDateTime wallClock(long millis) { + long days = floorDiv(millis, DAY); + return LocalDateTime.of(LocalDate.ofEpochDay(days), LocalTime.ofNanoOfDay((millis - days * DAY) * 1000000L)); + } + + private static long floorDiv(long value, long divisor) { + long quotient = value / divisor; + return value % divisor != 0 && (value < 0) != (divisor < 0) ? quotient - 1 : quotient; + } +} diff --git a/docs/developer-guide/Annotation-SQLite-ORM.asciidoc b/docs/developer-guide/Annotation-SQLite-ORM.asciidoc index 878ad66d5db..44657ec1876 100644 --- a/docs/developer-guide/Annotation-SQLite-ORM.asciidoc +++ b/docs/developer-guide/Annotation-SQLite-ORM.asciidoc @@ -52,8 +52,10 @@ write a loaded value into it. Java type (`String -> TEXT`, `int/long -> INTEGER`, `float/double -> REAL`, `boolean -> INTEGER`, `java.util.Date -> INTEGER` (epoch millis), + `Instant`, `LocalDateTime -> INTEGER` (epoch millis), + `LocalDate -> INTEGER` (epoch day), `byte[] -> BLOB`). -| `@Temporal` | Stores a `java.util.Date` in a native date or time +| `@Temporal` | Stores a date or time field in a native date or time column instead of epoch milliseconds. See <>. | `@Column(nullable=false)`| Adds `NOT NULL` to the column declaration. @@ -454,7 +456,28 @@ represent exactly are rejected rather than converted. A value whose text carries a time-zone offset, such as one read from a PostgreSQL `timestamptz` column, reads as the instant it names. -`@Temporal` applies to entity fields of type `java.util.Date`. It can't be +`java.time.Instant`, `LocalDate`, and `LocalDateTime` fields map without an +annotation, to the same portable integer columns: + +[cols="1,2,2", options="header"] +|=== +| Field type | Default column | With `@Temporal` +| `Instant` | epoch milliseconds, the same value a `Date` or a `long` of `System.currentTimeMillis()` holds | `TIMESTAMP` +| `LocalDateTime` | milliseconds since `1970-01-01T00:00` of the wall clock, with no zone applied | `TIMESTAMP`, the wall clock as written +| `LocalDate` | days since `1970-01-01` | `DATE` +|=== + +Because an `Instant` stores the same number, changing a `long` or `Date` field of +epoch milliseconds to an `Instant` reads the rows already in the table. Pass an +`Instant`, `LocalDate`, or `LocalDateTime` as the query parameter for one of +these fields, not a number. Precision is milliseconds, as for a `Date`; finer +digits are dropped on write. A `LocalDate` takes only `@Temporal(TemporalType.DATE)` +and the other two only `TIMESTAMP`. `LocalTime`, `OffsetDateTime`, and +`ZonedDateTime` aren't mapped; store an `Instant` and keep the zone in its own +field when it matters. + +`@Temporal` applies to entity fields of type `java.util.Date`, `Instant`, +`LocalDate`, and `LocalDateTime`. It can't be combined with `@Convert`, used on an identifier or version, or applied to element-collection values. A field with `@Temporal` requires `openSession()`. An explicit `@Column(type)` on one must name a matching date type, such as diff --git a/maven/build-engine/src/main/java/com/codename1/maven/processors/OrmAnnotationProcessor.java b/maven/build-engine/src/main/java/com/codename1/maven/processors/OrmAnnotationProcessor.java index aa6a9e07e84..d9355d36bc6 100644 --- a/maven/build-engine/src/main/java/com/codename1/maven/processors/OrmAnnotationProcessor.java +++ b/maven/build-engine/src/main/java/com/codename1/maven/processors/OrmAnnotationProcessor.java @@ -460,7 +460,7 @@ private void processClass(AnnotatedClass cls, ProcessorContext ctx, boolean from if (relationship != null) { // Element collections and relationships keep their own column // format; a @Temporal there would be silently ignored. - if(f.getAnnotation("Lcom/codename1/annotations/db/Temporal;")!=null) { ctx.error(cls,"@Temporal applies to a single java.util.Date field, not a relationship or collection: "+fieldPath.path);continue; } + if(f.getAnnotation("Lcom/codename1/annotations/db/Temporal;")!=null) { ctx.error(cls,"@Temporal applies to a single date or time field, not a relationship or collection: "+fieldPath.path);continue; } if(fieldPath.prefix.length()>0) { ctx.error(cls,"Relationships inside embeddables are not supported: "+fieldPath.path);continue; } relationship.declaringType=fieldPath.declaringType;relationship.index=ec.relations.size(); ec.relations.add(relationship); continue; } PersistedField pf = new PersistedField(); @@ -489,15 +489,32 @@ private void processClass(AnnotatedClass cls, ProcessorContext ctx, boolean from // parameters all take the path a @Convert field already takes. Object value=temporal.get("value"); boolean day=value instanceof String[] && "DATE".equals(((String[])value)[1]); + String javaTime=JAVA_TIME_TYPES.get(f.getDescriptor()); if(conversion!=null) ctx.error(cls,"@Temporal cannot be combined with @Convert: "+pf.fieldName); - else if(!"Ljava/util/Date;".equals(f.getDescriptor())) ctx.error(cls,"@Temporal requires a java.util.Date field: "+pf.fieldName); + else if(!"Ljava/util/Date;".equals(f.getDescriptor()) && javaTime==null) ctx.error(cls,"@Temporal requires a java.util.Date, Instant, LocalDate or LocalDateTime field: "+pf.fieldName); else if(f.getAnnotation(ID_DESC)!=null || pf.version || ec.embeddedId!=null && pf.fieldName.startsWith(ec.embeddedId+".")) ctx.error(cls,"Identifier and version fields cannot be @Temporal: "+pf.fieldName); + // A LocalDate has no time to keep and the other two have no + // single day to be: the type already says which column it is. + else if(javaTime!=null && day!="LocalDate".equals(javaTime)) ctx.error(cls,"@Temporal("+(day?"DATE":"TIMESTAMP")+") does not hold a java.time."+javaTime+": "+pf.fieldName); else { - pf.converter="com.codename1.impl.orm.TemporalConverter."+(day?"Day":"Timestamp"); - pf.domainType="java.util.Date"; + pf.converter=javaTime==null?"com.codename1.impl.orm.TemporalConverter."+(day?"Day":"Timestamp") + :"com.codename1.impl.orm.JavaTimeConverter."+javaTime+(day?"Day":"Timestamp"); + pf.domainType=javaTime==null?"java.util.Date":"java.time."+javaTime; pf.kind=PropertyTypeKind.scalar("java.lang.String"); pf.temporal=day?1:2; } + } else if(conversion==null && JAVA_TIME_TYPES.containsKey(f.getDescriptor())) { + // java.time takes Date's portable default, a number in an integer + // column, through a built-in converter: an Instant reads what a + // long or a Date of milliseconds wrote. + String javaTime=JAVA_TIME_TYPES.get(f.getDescriptor()); + if(f.getAnnotation(ID_DESC)!=null || ec.embeddedId!=null && pf.fieldName.startsWith(ec.embeddedId+".")) ctx.error(cls,"Identifier fields cannot be java.time values: "+pf.fieldName); + else if(pf.version) ctx.error(cls,"Version fields cannot be java.time values: "+pf.fieldName); + else { + pf.converter="com.codename1.impl.orm.JavaTimeConverter."+javaTime+("LocalDate".equals(javaTime)?"EpochDay":"Millis"); + pf.domainType="java.time."+javaTime; + pf.kind=PropertyTypeKind.scalar("java.lang.Long"); + } } AnnotatedClass enumClass = pf.kind.kind == PropertyTypeKind.Kind.REFERENCE ? findType(pf.kind.binaryName,ctx) : null; if (pf.kind.kind == PropertyTypeKind.Kind.REFERENCE && enumClass != null && enumClass.isEnum()) @@ -1135,6 +1152,15 @@ && lowerOrDigit(name.charAt(i-1)) && lowerOrDigit(name.charAt(i+1))) return out.toString().toLowerCase(java.util.Locale.ROOT); } + /// The java.time field types the ORM maps, by descriptor, to the simple name + /// JavaTimeConverter's nested converters start with. + private static final java.util.Map JAVA_TIME_TYPES=new java.util.HashMap(); + static { + JAVA_TIME_TYPES.put("Ljava/time/Instant;","Instant"); + JAVA_TIME_TYPES.put("Ljava/time/LocalDate;","LocalDate"); + JAVA_TIME_TYPES.put("Ljava/time/LocalDateTime;","LocalDateTime"); + } + /// Whether a declared column type holds a @Temporal value of the given kind /// (1 DATE, 2 TIMESTAMP), at millisecond precision. TEXT holds either: SQLite has no date type and /// schemas written for it declare their dates as TEXT. Mirrors SessionImpl's diff --git a/maven/build-engine/src/test/java/com/codename1/maven/processors/OrmAnnotationProcessorTest.java b/maven/build-engine/src/test/java/com/codename1/maven/processors/OrmAnnotationProcessorTest.java index 38f0e3447f5..1e19adbc2dd 100644 --- a/maven/build-engine/src/test/java/com/codename1/maven/processors/OrmAnnotationProcessorTest.java +++ b/maven/build-engine/src/test/java/com/codename1/maven/processors/OrmAnnotationProcessorTest.java @@ -1399,7 +1399,65 @@ public void temporalFieldsRejectAColumnTypeThatCannotHoldThem() throws Exception + "@Entity public class Diary { @Id public long id; @Temporal(TemporalType.DATE) @ElementCollection public List days=new ArrayList(); }"); JavaSourceCompiler.compile(sources,classes,Arrays.asList(testClassesDir())); String errors=runProcessor(classes,Collections.emptyList()).getErrors().toString(); - assertTrue(errors,errors.contains("@Temporal applies to a single java.util.Date field, not a relationship or collection: days")); + assertTrue(errors,errors.contains("@Temporal applies to a single date or time field, not a relationship or collection: days")); + } + + /// Instant, LocalDate and LocalDateTime map without an annotation, to the + /// numbers a Date's default writes, and to native columns under @Temporal. + /// Both models store, load, bind a query parameter and order by each one. + @Test + public void javaTimeFieldsRoundTripAndQuery() throws Exception { + File classes=tmp.newFolder("javatime");Map sources=new java.util.LinkedHashMap(); + sources.put("javatime.Event","package javatime; import com.codename1.annotations.*; import com.codename1.annotations.db.*; import java.time.*; " + + "@Entity public class Event { @Id public long id; public Instant at; public LocalDate day; public LocalDateTime local; " + + "@Temporal(TemporalType.TIMESTAMP) public Instant nativeAt; @Temporal(TemporalType.DATE) public LocalDate nativeDay; @Temporal(TemporalType.TIMESTAMP) public LocalDateTime nativeLocal; public long rawAt; }"); + JavaSourceCompiler.compile(sources,classes,Arrays.asList(testClassesDir())); + ProcessorContext client=runProcessor(classes);assertFalse(client.getErrors().toString(),client.hasErrors()); + ProcessorContext backend=runProcessor(classes,backendClasspath());assertFalse(backend.getErrors().toString(),backend.hasErrors()); + java.time.Instant early=java.time.Instant.parse("1969-07-20T20:17:40.123456Z"),late=java.time.Instant.parse("2026-10-24T09:30:00.250Z"); + try(java.net.URLClassLoader loader=new java.net.URLClassLoader(new URL[]{classes.toURI().toURL()},getClass().getClassLoader())) { + Class type=loader.loadClass("javatime.Event"); + for(String suffix:Arrays.asList("Cn1Model","Cn1BackendModel")) { + Map> models=new java.util.LinkedHashMap>();models.put(type.getName(),(com.codename1.impl.orm.EntityModel)loader.loadClass(type.getName()+suffix).newInstance()); + com.codename1.backend.Database db=com.codename1.backend.Database.open(":memory:");com.codename1.orm.session.Session session=new com.codename1.impl.orm.SessionImpl(new com.codename1.impl.orm.BackendSqlAccess(null,db,db.dialect()),models); + try { + session.createTables();session.beginTransaction(); + for(java.time.Instant at:Arrays.asList(late,early)) { + Object e=type.newInstance();java.time.LocalDateTime local=java.time.LocalDateTime.ofInstant(at,java.time.ZoneOffset.UTC); + type.getField("at").set(e,at);type.getField("nativeAt").set(e,at);type.getField("day").set(e,local.toLocalDate());type.getField("nativeDay").set(e,local.toLocalDate()); + type.getField("local").set(e,local);type.getField("nativeLocal").set(e,local);type.getField("rawAt").setLong(e,at.toEpochMilli());session.persist(e); + } + Object empty=type.newInstance();session.persist(empty);session.commitTransaction();session.clear(); + for(String field:Arrays.asList("at","nativeAt","day","nativeDay","local","nativeLocal")) { + java.util.List rows=session.createQuery("select e from Event e where e."+field+" is not null order by e."+field).list(); + assertEquals(suffix+" "+field,2,rows.size()); + Object first=rows.get(0),second=rows.get(1); + // Milliseconds are kept, finer digits are dropped. + java.time.Instant truncated=java.time.Instant.ofEpochMilli(early.toEpochMilli()); + Object expected=field.toLowerCase().endsWith("day")?java.time.LocalDate.of(1969,7,20) + :field.toLowerCase().endsWith("local")?java.time.LocalDateTime.ofInstant(truncated,java.time.ZoneOffset.UTC):truncated; + assertEquals(suffix+" "+field,expected,type.getField(field).get(first)); + Object after=session.createQuery("select e from Event e where e."+field+" > :v").setParameter("v",expected).first(); + assertEquals(suffix+" "+field,type.getField(field).get(second),type.getField(field).get(after)); + } + // The default Instant column is the epoch milliseconds a long holds. + assertEquals(1,session.createQuery("select e from Event e where e.rawAt = :v").setParameter("v",late.toEpochMilli()).list().size()); + Object loadedEmpty=session.find(type,type.getField("id").get(empty)); + for(String field:Arrays.asList("at","nativeAt","day","nativeDay","local","nativeLocal")) org.junit.Assert.assertNull(suffix+" "+field,type.getField(field).get(loadedEmpty)); + } finally { session.close();db.close(); } + } + } + String[][] rejected={{"@Temporal(TemporalType.DATE) public java.time.Instant at;","@Temporal(DATE) does not hold a java.time.Instant: at"}, + {"@Temporal(TemporalType.TIMESTAMP) public java.time.LocalDate at;","@Temporal(TIMESTAMP) does not hold a java.time.LocalDate: at"}, + {"@Temporal(TemporalType.DATE) public java.time.LocalDateTime at;","@Temporal(DATE) does not hold a java.time.LocalDateTime: at"}, + {"@Temporal public java.time.LocalTime at;","@Temporal requires a java.util.Date, Instant, LocalDate or LocalDateTime field: at"}}; + for(String[] c:rejected) { + File bad=tmp.newFolder();Map badSources=new java.util.LinkedHashMap(); + badSources.put("javatimebad.Entry","package javatimebad; import com.codename1.annotations.*; import com.codename1.annotations.db.*; @Entity public class Entry { @Id public long id; "+c[0]+" }"); + JavaSourceCompiler.compile(badSources,bad,Arrays.asList(testClassesDir())); + String errors=runProcessor(bad,Collections.emptyList()).getErrors().toString(); + assertTrue(errors,errors.contains(c[1])); + } } @Test From f39fd3cb2662836fc034f2ad771dbb5093bce692 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 24 Oct 2026 05:29:16 +0300 Subject: [PATCH 2/8] Samples: store entity timestamps as java.time.Instant Wayline, Savor, Parley and Skirmish entities hold Instant instead of epoch millisecond longs. The ORM's default Instant mapping is the same BIGINT, so no migration changes; NOT NULL "unset" sentinels are Instant.EPOCH and the wire DTOs keep epoch milliseconds. Co-Authored-By: Claude Opus 5.5 --- .../com/codenameone/examples/parley/Rows.java | 13 +++++- .../parley/account/AccountCleanup.java | 3 +- .../examples/parley/account/Accounts.java | 5 ++- .../examples/parley/account/Moderation.java | 9 ++-- .../parley/account/PhoneVerification.java | 23 +++++----- .../examples/parley/admin/Statistics.java | 17 +++---- .../examples/parley/bridge/Bridges.java | 9 ++-- .../examples/parley/call/Calls.java | 21 ++++----- .../examples/parley/chat/Conversations.java | 25 ++++++----- .../examples/parley/chat/Fanout.java | 11 ++--- .../examples/parley/chat/Media.java | 5 ++- .../examples/parley/chat/Messages.java | 19 ++++---- .../examples/parley/contact/Contacts.java | 13 +++--- .../examples/parley/device/Devices.java | 13 +++--- .../examples/parley/domain/BridgeEvent.java | 9 ++-- .../examples/parley/domain/BridgeLink.java | 7 +-- .../examples/parley/domain/CallRecord.java | 19 ++++---- .../examples/parley/domain/ClosedAccount.java | 7 +-- .../examples/parley/domain/ContactBlock.java | 7 +-- .../examples/parley/domain/Conversation.java | 13 +++--- .../parley/domain/ConversationPhoto.java | 7 +-- .../examples/parley/domain/Device.java | 13 +++--- .../examples/parley/domain/Envelope.java | 13 +++--- .../examples/parley/domain/InviteLink.java | 13 +++--- .../examples/parley/domain/LiveTicket.java | 7 +-- .../examples/parley/domain/MediaBlob.java | 7 +-- .../examples/parley/domain/Membership.java | 7 +-- .../examples/parley/domain/MessageLog.java | 7 +-- .../parley/domain/ModerationEvent.java | 7 +-- .../examples/parley/domain/PhoneCode.java | 19 ++++---- .../examples/parley/domain/Profile.java | 13 +++--- .../examples/parley/domain/ProfilePhoto.java | 7 +-- .../examples/parley/domain/PushDevice.java | 7 +-- .../examples/parley/domain/Report.java | 7 +-- .../examples/parley/live/LiveTickets.java | 7 +-- .../examples/parley/push/PushDevices.java | 5 ++- .../repository/BridgeEventRepository.java | 3 +- .../repository/CallRecordRepository.java | 13 +++--- .../repository/ConversationRepository.java | 3 +- .../parley/repository/DeviceRepository.java | 3 +- .../parley/repository/EnvelopeRepository.java | 7 +-- .../repository/LiveTicketRepository.java | 3 +- .../repository/MediaBlobRepository.java | 5 ++- .../repository/MessageLogRepository.java | 7 +-- .../repository/ModerationEventRepository.java | 3 +- .../parley/repository/ProfileRepository.java | 5 ++- .../com/codenameone/examples/savor/Rows.java | 8 ++++ .../savor/account/AccountCleanup.java | 3 +- .../examples/savor/account/Accounts.java | 5 ++- .../examples/savor/account/DemoAccounts.java | 9 ++-- .../examples/savor/account/Moderation.java | 12 ++--- .../savor/account/PhoneVerification.java | 21 ++++----- .../examples/savor/admin/Statistics.java | 19 ++++---- .../examples/savor/catalog/Catalog.java | 3 +- .../savor/catalog/DemoRestaurants.java | 13 +++--- .../examples/savor/catalog/Restaurants.java | 29 ++++++------ .../examples/savor/courier/Couriers.java | 11 ++--- .../examples/savor/courier/Earnings.java | 11 ++--- .../examples/savor/delivery/Deliveries.java | 40 +++++++++-------- .../examples/savor/delivery/Matcher.java | 3 +- .../examples/savor/domain/ClosedAccount.java | 7 +-- .../savor/domain/CourierApplication.java | 19 ++++---- .../savor/domain/CourierDocument.java | 7 +-- .../examples/savor/domain/CourierState.java | 7 +-- .../examples/savor/domain/CustomerOrder.java | 31 ++++++------- .../examples/savor/domain/Delivery.java | 25 ++++++----- .../savor/domain/DeliveryActivity.java | 13 +++--- .../examples/savor/domain/DeliveryEvent.java | 7 +-- .../examples/savor/domain/Favorite.java | 7 +-- .../examples/savor/domain/LiveTicket.java | 7 +-- .../savor/domain/ModerationEvent.java | 7 +-- .../examples/savor/domain/OrderEvent.java | 7 +-- .../examples/savor/domain/Payment.java | 13 +++--- .../examples/savor/domain/PaymentMethod.java | 7 +-- .../examples/savor/domain/PaymentSetup.java | 7 +-- .../examples/savor/domain/Payout.java | 7 +-- .../examples/savor/domain/PhoneCode.java | 19 ++++---- .../examples/savor/domain/Photo.java | 7 +-- .../examples/savor/domain/Pricing.java | 7 +-- .../examples/savor/domain/Profile.java | 7 +-- .../examples/savor/domain/Promo.java | 7 +-- .../examples/savor/domain/PushDevice.java | 7 +-- .../examples/savor/domain/Restaurant.java | 13 +++--- .../examples/savor/domain/SavedAddress.java | 7 +-- .../examples/savor/live/LiveTickets.java | 7 +-- .../savor/onboarding/Applications.java | 23 +++++----- .../examples/savor/order/Addresses.java | 3 +- .../examples/savor/order/DemoKitchen.java | 7 +-- .../examples/savor/order/DemoOrders.java | 27 +++++------ .../examples/savor/order/OrderEvents.java | 3 +- .../examples/savor/order/Orders.java | 30 +++++++------ .../examples/savor/order/Promos.java | 3 +- .../examples/savor/order/Quotes.java | 5 ++- .../examples/savor/pay/Payments.java | 38 ++++++++-------- .../examples/savor/push/OrderPushes.java | 21 ++++----- .../examples/savor/push/PushDevices.java | 5 ++- .../CourierApplicationRepository.java | 7 +-- .../repository/CourierDocumentRepository.java | 3 +- .../repository/CourierStateRepository.java | 5 ++- .../repository/CustomerOrderRepository.java | 35 ++++++++------- .../DeliveryActivityRepository.java | 21 +++++---- .../repository/DeliveryEventRepository.java | 3 +- .../savor/repository/DeliveryRepository.java | 41 ++++++++--------- .../repository/LiveTicketRepository.java | 3 +- .../repository/ModerationEventRepository.java | 3 +- .../repository/PaymentMethodRepository.java | 3 +- .../savor/repository/PaymentRepository.java | 3 +- .../repository/PaymentSetupRepository.java | 5 ++- .../savor/repository/PricingRepository.java | 3 +- .../savor/repository/ProfileRepository.java | 3 +- .../examples/skirmish/account/Accounts.java | 5 ++- .../skirmish/admin/AdminEndpoint.java | 5 ++- .../examples/skirmish/admin/Flags.java | 5 ++- .../examples/skirmish/admin/Moderation.java | 14 +++--- .../examples/skirmish/domain/AdminAction.java | 7 +-- .../examples/skirmish/domain/Broadcast.java | 7 +-- .../examples/skirmish/domain/Flag.java | 7 +-- .../examples/skirmish/domain/ForgeAsset.java | 7 +-- .../examples/skirmish/domain/ForgePack.java | 13 +++--- .../skirmish/domain/ForgePackVersion.java | 7 +-- .../examples/skirmish/domain/GameTicket.java | 7 +-- .../examples/skirmish/domain/MatchRecord.java | 7 +-- .../skirmish/domain/MissionStars.java | 7 +-- .../examples/skirmish/domain/Pipeline.java | 7 +-- .../examples/skirmish/domain/PipelineHit.java | 7 +-- .../examples/skirmish/domain/Profile.java | 19 ++++---- .../examples/skirmish/domain/PushDevice.java | 7 +-- .../examples/skirmish/domain/Referral.java | 13 +++--- .../skirmish/domain/ReferralCode.java | 7 +-- .../examples/skirmish/domain/Spotlight.java | 7 +-- .../skirmish/domain/StorePurchase.java | 7 +-- .../examples/skirmish/forge/Forge.java | 25 ++++++----- .../examples/skirmish/game/GameEndpoint.java | 4 +- .../examples/skirmish/game/GameTickets.java | 9 ++-- .../examples/skirmish/game/Results.java | 5 ++- .../examples/skirmish/push/PushDevices.java | 5 ++- .../repository/BroadcastRepository.java | 3 +- .../repository/ForgeAssetRepository.java | 3 +- .../repository/GameTicketRepository.java | 3 +- .../repository/MatchRecordRepository.java | 5 ++- .../repository/ProfileRepository.java | 7 +-- .../repository/StorePurchaseRepository.java | 3 +- .../examples/skirmish/shop/Shop.java | 3 +- .../examples/skirmish/social/Audience.java | 4 +- .../examples/skirmish/social/Insights.java | 21 ++++----- .../examples/skirmish/social/Pipelines.java | 13 +++--- .../examples/skirmish/social/Promotion.java | 19 ++++---- .../examples/skirmish/social/Referrals.java | 11 ++--- .../examples/wayline/account/Accounts.java | 9 ++-- .../wayline/account/DemoAccounts.java | 11 ++--- .../examples/wayline/account/Moderation.java | 14 +++--- .../wayline/account/PhoneVerification.java | 23 +++++----- .../examples/wayline/admin/Statistics.java | 35 ++++++++++----- .../wayline/domain/ClosedAccount.java | 7 +-- .../wayline/domain/DriverApplication.java | 19 ++++---- .../wayline/domain/DriverDocument.java | 7 +-- .../examples/wayline/domain/DriverState.java | 7 +-- .../examples/wayline/domain/LiveTicket.java | 7 +-- .../wayline/domain/ModerationEvent.java | 7 +-- .../examples/wayline/domain/Payment.java | 13 +++--- .../wayline/domain/PaymentMethod.java | 7 +-- .../examples/wayline/domain/PaymentSetup.java | 7 +-- .../examples/wayline/domain/Payout.java | 7 +-- .../examples/wayline/domain/PhoneCode.java | 19 ++++---- .../examples/wayline/domain/Pricing.java | 7 +-- .../examples/wayline/domain/Profile.java | 7 +-- .../examples/wayline/domain/PushDevice.java | 7 +-- .../examples/wayline/domain/Ride.java | 25 ++++++----- .../examples/wayline/domain/RideActivity.java | 13 +++--- .../examples/wayline/domain/RideEvent.java | 7 +-- .../examples/wayline/driver/Drivers.java | 15 ++++--- .../examples/wayline/driver/Earnings.java | 11 ++--- .../wayline/driving/Applications.java | 24 +++++----- .../examples/wayline/live/LiveTickets.java | 9 ++-- .../examples/wayline/pay/Payments.java | 34 +++++++------- .../examples/wayline/push/PushDevices.java | 7 +-- .../examples/wayline/push/RidePushes.java | 25 ++++++----- .../DriverApplicationRepository.java | 7 +-- .../repository/DriverDocumentRepository.java | 3 +- .../repository/DriverStateRepository.java | 5 ++- .../repository/LiveTicketRepository.java | 3 +- .../repository/ModerationEventRepository.java | 3 +- .../repository/PaymentMethodRepository.java | 3 +- .../wayline/repository/PaymentRepository.java | 3 +- .../repository/PaymentSetupRepository.java | 5 ++- .../wayline/repository/PricingRepository.java | 3 +- .../wayline/repository/ProfileRepository.java | 3 +- .../repository/RideActivityRepository.java | 20 +++++---- .../repository/RideEventRepository.java | 3 +- .../wayline/repository/RideRepository.java | 43 +++++++++--------- .../examples/wayline/ride/DemoRides.java | 15 ++++--- .../examples/wayline/ride/Fares.java | 5 ++- .../examples/wayline/ride/Matcher.java | 3 +- .../examples/wayline/ride/Rides.java | 45 ++++++++++--------- 194 files changed, 1156 insertions(+), 916 deletions(-) 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..b7f3edff059 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,15 @@ 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). @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, From 3bd574a6ccb5de5af7aca409d3c195dcfe46ed9c Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 24 Oct 2026 06:19:32 +0300 Subject: [PATCH 3/8] ORM: harden java.time mapping after review Refuse a LocalDateTime past a long of milliseconds instead of wrapping it, report java.time identifier/version/@Temporal misuse once rather than also as a relationship, refuse Property with a clear error instead of generated code that fails to compile, and test embedded Instants and max/min aggregates. Co-Authored-By: Claude Opus 5.5 --- .../codename1/impl/orm/JavaTimeConverter.java | 12 +++++- .../processors/OrmAnnotationProcessor.java | 13 ++++++- .../OrmAnnotationProcessorTest.java | 39 ++++++++++++++++++- .../repository/ProfileRepository.java | 3 +- 4 files changed, 60 insertions(+), 7 deletions(-) diff --git a/CodenameOne/src/com/codename1/impl/orm/JavaTimeConverter.java b/CodenameOne/src/com/codename1/impl/orm/JavaTimeConverter.java index 3d102178025..e30c079e63b 100644 --- a/CodenameOne/src/com/codename1/impl/orm/JavaTimeConverter.java +++ b/CodenameOne/src/com/codename1/impl/orm/JavaTimeConverter.java @@ -39,7 +39,7 @@ /// reads a column a `long createdAt` or a `Date` wrote, unchanged. /// /// `@Temporal` opts into a native column instead, through the same UTC ISO text -/// [TemporalConverter] writes: `TIMESTAMP` for an Instant or a LocalDateTime, +/// `TemporalConverter` writes: `TIMESTAMP` for an Instant or a LocalDateTime, /// `DATE` for a LocalDate. /// /// Precision is the millisecond, as for a Date: nanoseconds below it are dropped @@ -147,8 +147,16 @@ public LocalDateTime fromDatabase(String value) { } } + /// Milliseconds of a wall clock, refusing what a long cannot hold: a + /// LocalDateTime reaches the year 999999999, and `LocalDateTime.MAX` as a + /// "no bound" value would otherwise wrap to a plausible wrong time. An + /// Instant needs no such check; its toEpochMilli throws by itself. static long millis(LocalDateTime value) { - return value.toLocalDate().toEpochDay() * DAY + value.toLocalTime().toNanoOfDay() / 1000000L; + long days = value.toLocalDate().toEpochDay(); + if (days > Long.MAX_VALUE / DAY - 1 || days < Long.MIN_VALUE / DAY + 1) { + throw new IllegalArgumentException("A LocalDateTime does not fit in epoch milliseconds: " + value); + } + return days * DAY + value.toLocalTime().toNanoOfDay() / 1000000L; } static LocalDateTime wallClock(long millis) { diff --git a/maven/build-engine/src/main/java/com/codename1/maven/processors/OrmAnnotationProcessor.java b/maven/build-engine/src/main/java/com/codename1/maven/processors/OrmAnnotationProcessor.java index d9355d36bc6..056bf99f25f 100644 --- a/maven/build-engine/src/main/java/com/codename1/maven/processors/OrmAnnotationProcessor.java +++ b/maven/build-engine/src/main/java/com/codename1/maven/processors/OrmAnnotationProcessor.java @@ -508,14 +508,23 @@ private void processClass(AnnotatedClass cls, ProcessorContext ctx, boolean from // column, through a built-in converter: an Instant reads what a // long or a Date of milliseconds wrote. String javaTime=JAVA_TIME_TYPES.get(f.getDescriptor()); - if(f.getAnnotation(ID_DESC)!=null || ec.embeddedId!=null && pf.fieldName.startsWith(ec.embeddedId+".")) ctx.error(cls,"Identifier fields cannot be java.time values: "+pf.fieldName); - else if(pf.version) ctx.error(cls,"Version fields cannot be java.time values: "+pf.fieldName); + if(f.getAnnotation(ID_DESC)!=null || ec.embeddedId!=null && pf.fieldName.startsWith(ec.embeddedId+".")) { ctx.error(cls,"Identifier fields cannot be java.time values: "+pf.fieldName);continue; } + else if(pf.version) { ctx.error(cls,"Version fields cannot be java.time values: "+pf.fieldName);continue; } else { pf.converter="com.codename1.impl.orm.JavaTimeConverter."+javaTime+("LocalDate".equals(javaTime)?"EpochDay":"Millis"); pf.domainType="java.time."+javaTime; pf.kind=PropertyTypeKind.scalar("java.lang.Long"); } } + // A java.time field with no converter by now was refused above; it + // must not go on to be reported again as a relationship. + if(pf.converter==null && JAVA_TIME_TYPES.containsKey(f.getDescriptor())) continue; + // A Property holds its value through generated accessors that know + // only the scalar types; a converter has no hook there. + if(pf.kind.kind==PropertyTypeKind.Kind.PROPERTY && pf.kind.elementBinaryName!=null && pf.kind.elementBinaryName.startsWith("java.time.")) { + ctx.error(cls,"A Property of "+pf.kind.elementBinaryName+" is not supported; declare a plain java.time field instead: "+pf.fieldName); + continue; + } AnnotatedClass enumClass = pf.kind.kind == PropertyTypeKind.Kind.REFERENCE ? findType(pf.kind.binaryName,ctx) : null; if (pf.kind.kind == PropertyTypeKind.Kind.REFERENCE && enumClass != null && enumClass.isEnum()) pf.kind = PropertyTypeKind.enumType(pf.kind.binaryName); diff --git a/maven/build-engine/src/test/java/com/codename1/maven/processors/OrmAnnotationProcessorTest.java b/maven/build-engine/src/test/java/com/codename1/maven/processors/OrmAnnotationProcessorTest.java index 1e19adbc2dd..c30b32639c4 100644 --- a/maven/build-engine/src/test/java/com/codename1/maven/processors/OrmAnnotationProcessorTest.java +++ b/maven/build-engine/src/test/java/com/codename1/maven/processors/OrmAnnotationProcessorTest.java @@ -1410,7 +1410,8 @@ public void javaTimeFieldsRoundTripAndQuery() throws Exception { File classes=tmp.newFolder("javatime");Map sources=new java.util.LinkedHashMap(); sources.put("javatime.Event","package javatime; import com.codename1.annotations.*; import com.codename1.annotations.db.*; import java.time.*; " + "@Entity public class Event { @Id public long id; public Instant at; public LocalDate day; public LocalDateTime local; " - + "@Temporal(TemporalType.TIMESTAMP) public Instant nativeAt; @Temporal(TemporalType.DATE) public LocalDate nativeDay; @Temporal(TemporalType.TIMESTAMP) public LocalDateTime nativeLocal; public long rawAt; }"); + + "@Temporal(TemporalType.TIMESTAMP) public Instant nativeAt; @Temporal(TemporalType.DATE) public LocalDate nativeDay; @Temporal(TemporalType.TIMESTAMP) public LocalDateTime nativeLocal; public long rawAt; @Embedded public Span span=new Span(); }"); + sources.put("javatime.Span","package javatime; import com.codename1.annotations.db.*; import java.time.*; @Embeddable public class Span { public Instant until; }"); JavaSourceCompiler.compile(sources,classes,Arrays.asList(testClassesDir())); ProcessorContext client=runProcessor(classes);assertFalse(client.getErrors().toString(),client.hasErrors()); ProcessorContext backend=runProcessor(classes,backendClasspath());assertFalse(backend.getErrors().toString(),backend.hasErrors()); @@ -1425,7 +1426,8 @@ public void javaTimeFieldsRoundTripAndQuery() throws Exception { for(java.time.Instant at:Arrays.asList(late,early)) { Object e=type.newInstance();java.time.LocalDateTime local=java.time.LocalDateTime.ofInstant(at,java.time.ZoneOffset.UTC); type.getField("at").set(e,at);type.getField("nativeAt").set(e,at);type.getField("day").set(e,local.toLocalDate());type.getField("nativeDay").set(e,local.toLocalDate()); - type.getField("local").set(e,local);type.getField("nativeLocal").set(e,local);type.getField("rawAt").setLong(e,at.toEpochMilli());session.persist(e); + type.getField("local").set(e,local);type.getField("nativeLocal").set(e,local);type.getField("rawAt").setLong(e,at.toEpochMilli()); + Object span=type.getField("span").get(e);span.getClass().getField("until").set(span,at);session.persist(e); } Object empty=type.newInstance();session.persist(empty);session.commitTransaction();session.clear(); for(String field:Arrays.asList("at","nativeAt","day","nativeDay","local","nativeLocal")) { @@ -1440,6 +1442,13 @@ public void javaTimeFieldsRoundTripAndQuery() throws Exception { Object after=session.createQuery("select e from Event e where e."+field+" > :v").setParameter("v",expected).first(); assertEquals(suffix+" "+field,type.getField(field).get(second),type.getField(field).get(after)); } + java.util.List spans=session.createQuery("select e from Event e where e.span.until < :v").setParameter("v",late).list(); + assertEquals(suffix,1,spans.size()); + Object loadedSpan=type.getField("span").get(spans.get(0)); + assertEquals(suffix,java.time.Instant.ofEpochMilli(early.toEpochMilli()),loadedSpan.getClass().getField("until").get(loadedSpan)); + // An aggregate of the field answers the field's type, not its storage. + assertEquals(suffix,java.time.Instant.ofEpochMilli(late.toEpochMilli()),session.createQuery("select max(e.at) from Event e").first()); + assertEquals(suffix,java.time.LocalDate.of(1969,7,20),session.createQuery("select min(e.nativeDay) from Event e").first()); // The default Instant column is the epoch milliseconds a long holds. assertEquals(1,session.createQuery("select e from Event e where e.rawAt = :v").setParameter("v",late.toEpochMilli()).list().size()); Object loadedEmpty=session.find(type,type.getField("id").get(empty)); @@ -1460,6 +1469,32 @@ public void javaTimeFieldsRoundTripAndQuery() throws Exception { } } + /// Where java.time cannot go, the build says so once, in its own words -- + /// not as a relationship, and not as generated code that fails to compile. + @Test + public void javaTimeFieldsRejectUnsupportedPlacements() throws Exception { + String imports="package javatimeplace; import com.codename1.annotations.*; import com.codename1.annotations.db.*; import java.util.*; import java.time.*; "; + String[][] cases={ + {"@Id(autoIncrement=false) public Instant at; public long other;","Identifier fields cannot be java.time values: at"}, + {"@Id public long id; @Version public Instant at;","Version fields cannot be java.time values: at"}, + {"@Id public long id; public final com.codename1.properties.Property at=new com.codename1.properties.Property(\"at\");","A Property of java.time.Instant is not supported"}, + {"@Id(autoIncrement=false) @Temporal public Instant at; public long other;","Identifier and version fields cannot be @Temporal: at"}, + {"@Id public long id; @Temporal(TemporalType.DATE) public Instant at;","@Temporal(DATE) does not hold a java.time.Instant: at"}, + {"@Id public long id; @ElementCollection public List at=new ArrayList();","ElementCollection requires a supported scalar value: java.time.Instant"}}; + for(String[] c:cases) { + File classes=tmp.newFolder();Map sources=new java.util.LinkedHashMap(); + sources.put("javatimeplace.Entry",imports+"@Entity public class Entry { "+c[0]+" }"); + JavaSourceCompiler.compile(sources,classes,Arrays.asList(testClassesDir())); + String errors=runProcessor(classes,Collections.emptyList()).getErrors().toString(); + assertTrue(errors,errors.contains(c[1])); + assertFalse(errors,errors.contains("relationships are not yet supported")); + } + // A wall clock past what a long of milliseconds holds is refused, never wrapped. + org.junit.Assert.assertThrows(IllegalArgumentException.class,()->new com.codename1.impl.orm.JavaTimeConverter.LocalDateTimeMillis().toDatabase(java.time.LocalDateTime.MAX)); + org.junit.Assert.assertThrows(IllegalArgumentException.class,()->new com.codename1.impl.orm.JavaTimeConverter.LocalDateTimeMillis().toDatabase(java.time.LocalDateTime.MIN)); + org.junit.Assert.assertThrows(ArithmeticException.class,()->new com.codename1.impl.orm.JavaTimeConverter.InstantMillis().toDatabase(java.time.Instant.MAX)); + } + @Test public void booleanMappingsRejectNativeBooleanDeclarations() throws Exception { for(boolean backend:Arrays.asList(false,true)) for(String declaration:Arrays.asList("BOOLEAN","bool"," Boolean NOT NULL ")) { 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 b7f3edff059..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 @@ -49,7 +49,8 @@ public interface ProfileRepository extends CrudRepository { /// 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") Instant seenBefore, @Param("joined") Instant joinedAfter, PageRequest page); From 68718600e777baba0dd742b80f93a7592bce3754 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 24 Oct 2026 08:22:19 +0300 Subject: [PATCH 4/8] Initializr: resync sample templates after the Instant conversion Co-Authored-By: Claude Opus 5.5 --- .../src/main/resources/parley-modules.zip | Bin 613584 -> 617266 bytes .../src/main/resources/savor-modules.zip | Bin 3132552 -> 3137361 bytes .../src/main/resources/skirmish-modules.zip | Bin 676839 -> 679147 bytes .../src/main/resources/wayline-modules.zip | Bin 960206 -> 963412 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/scripts/initializr/common/src/main/resources/parley-modules.zip b/scripts/initializr/common/src/main/resources/parley-modules.zip index 5cdfc79667b332c94edf15a97dfcb5828bcec71e..064091cef09a979d1e16b6568db72a8c77836af6 100644 GIT binary patch delta 13285 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

bo4&lo7aj+^VhwH2aZ%XRKcIM#>ZVO1X{Fv#m- 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 DX;j5T delta 9747 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 Q#ynfHie-P||1+5X10HYLwg3PC diff --git a/scripts/initializr/common/src/main/resources/savor-modules.zip b/scripts/initializr/common/src/main/resources/savor-modules.zip index f66519b68a529f8c9e53c9133fff11129fa1cd96..c438df29fe5667cc149f08818bc408ea97c7b0ca 100644 GIT binary patch delta 20529 zcmbt+349dA^8X$=H#fPD&Cbs3F`Hv2;U)=?0O2MC5D+mYfovcWl8}U3LZZP3qL`pk zfC}M~+k`_JP{N@icyM?hyeB-LiWkCzry!!gnwjj(&L-=7|IeS#Cxou~R(ExEb#+fw z4a?UZS6^&DuC8xXH)(jk?Bw#=yp)#^A<~#?Z#F#%_(_jS-EJ zjZux!jWLa}jd6|fjR^?0~_ zYKtpCJ;N3Oq1l#9V%)5+)5OiJEH5dmm_Zd&Rh4BGwNzOJ#lxxM8o04suP@4=YG*oh z6#n5jjw%v+sV$<4D=0@rZCUL?YmLZITIMJ(p~`BgYDaMivZqj$)l?c)ihozkEidO= z#T5%{XX0Q|caHKJ2z!u@1jAOnx6kad^7678NZP7TXFJBB22!l^-!^Jqars<_&0brX zTU9xI<`^DM>bB~4Zt(wg;@6pXEh^Prk~TQ;b8q(<8%W%U#9LHAN3ZsZ%K32R-{yFr zZYJu;sD~2^Lv$GhIpxdhRH|ilP~UFKgr-LfesJO8L|-VH!uh}vj8fUT@@R5(g< zYHcK7UE-I6U4-wMI>eBnFROx-8?K@f&jhwulc+CqgcQ*tEx~y+4*?TW> zV?5^^31`aM?6b=%=GF-Ms$olt7uMv=sHBppA^0!*m=U8#kC*_>waF2rIo9xLVAn#< zEUqYVl#HmbkvSH_6KbQgf5l8BkS$XOb4DkJLzC6uMf9xUice&h9ANx|(nDaHArkiG z(NQFqGfWHC{j1K}t$VOa)jgQ(>u(6?tWKy(WRuB{0}ZRZeLMPvx?DqYN=JjjX;b|v z=a7ODG6k#S4cW=DH`fp+DJnOA?BL;4236sh@2IJ@SCvZ&OCOEX;raMKU?ho=_TuTa zWt9~vys6jlzl%$29o6=-njHQ&i^JK_a0MdYBjn6CM!?vihTD>`MP6n*G<{+5CH2D$ z71|)BP5(I3pi%3ddFNlA_ zhNkjF9Tb!&_F0o>_^b=t_$1FTD%fo>s=zQ*?M5qk$Z$a&;#8lY8e1k@DKt>fR%q~t z;v&O%NplJl;1!=t4IVorw{Sx4;IVl_CZM6Er=_KhhR{+&G<;QLu*Nz&cIUK_pkl*J zuSnG7AO|`QhjZ%-8#X713J34`1{2IWkfI|O90osikh3d6MhGi4M8Wk^1E-`D;|#+@ zZ_nNKfy)CE{mF%LgVtYdg!EDau5p(#jGLAiL8y6#9{qJ6UG$3@*IT6;*IV=#dmiK> z$=(BoV?LdBKNKC(TgY=q4XuG`PJ!L$PNh;~ifgCOL^~QfK6k?KLUCi-;Km>{p6a&@ zX{Ih&g-wi}y}DMgJJR-+;WO{}E}=DL71JFy*z}U#3A$y{VN8N{;|RCHLydt0aQ)djEad>HMmo& zsw+#&${jWK4wAI+3N^V-VAtn{(SeGS;Lpzu1;M(4q{#z=2dGrR17MRElLAJudde&aLpn}DDd^ zx$w|fmFl6faL!5%Cfhh_us1C3Nd+o;TY8U;A@_PxYkPL@a#{E-lS;9@)9~*y^dC0d zF@1aY#683B8e=Jy2fRuZ|Ea)f&B7El`IFCJ&TM1M-x?HvS4#zATDSn@N zLF4A4?|w)z7S|3*@4M9BH3K@jp{5BA)cp`t+yo}(O`MQBq%eQ@*!#v74jZ2{IM)XG ze^7T}zz|ZeQ#=FG z|6_`JMQfZBqTBHOx~NqdD%GkC!Do^qA;yDUxJ!yyCzG>L#vzf)Nkc%2@hi`3O>U$Z zzmIeZX;-)oag*_Xo1uNMF&cg!WIXa$M&F0OAmvPPx?ys5u|&D&i+e)McFH&wki+>ioI z-e$iwuP1pEDu})kt(*$^(?oyhKD~=cbg~i#NTNtwGM&fjde3SsjIgOx5jOGeR#(jV zlS30|=;9tA*!Rx+X?2*zxdOr(DqN}Sl?}pPObjPqm(kyL(=9vs?U$RiD%EB!|K>Ib zexJs5gVFiSc4$9C`-VMSJg?ZUczZj)gdQX9bZUBeWexvo=;Fr3i>_@c{V(ZdBCMVs z6WAe}zyikMOcX4sr<43ojk&LWd6-JIoV3-`YPF|fTN~&Py__#~)O38WsqJ#y=Evz& z#yM2Y+-bARYCQvKC$QQvuMA(Sx|+zi{mdvb@o)4bKWRFxPt*BQqh&WUL~4v`q9+AA zI~7L<;}>)koNA&|!<-LhIBLfW1Hzmy=opA>rqiV!MmEzobl$2(J2+pJit~l^!5Ap1 zUrnF#q?qhy=ouPmB6F+CD~s_xxQi9xH3P?K#*h5)9KBj2jo7f3o*>CA^24}hI+EO4 zOUHWaTGuaZJnyGco%iEC?I4)4fj;a(7Pyhm#1eKR{iAFk<;69%6C92TcLO2DO?0G} zBt*tGdW^F{R&JwLsC6l2ujxOcRH~2gm5#T}qV4o`4+E3D9kjQ<(^pbe<;BxIsz6dz z@$~7AD$llIaIO{~En4V7pOU4OILgcBIjTL5Dp~H_suB;Dn;yj!z`b8+8j8--R&sMc zy*t$ThD)Kz` zPB$jR!xqAowRAY-yh)oS(8F)ilOzc`W+;x5c9Zsnt8da4340D0c~7ibz~sT-VwnZd z8p{MiRX4^L2EIiv)lGi6Y5enXD%JCG{JRgXX({IiHQ{)Yh z&K^$u&eAiyC8bw8=FG)V$p4Sh`Ay;UnpCC2@4H(pC|!$i&`-nwV|gcF&N3QLiu3e? z0g`%7d`?f28gXCHBc+DB;)Xcy3jCT2ClO>%W%Q7AiS8#c&A8;Uu_nC-?ACsd|vs@917?4~9ej`8^#aJ4lZwhbS;f_=%n* z`$mPQuRqKTC*7{o%Od=P+iqWJ^iruBp~Z{&Rq#ro?nfnLC*uWsr#G`y3PyT9w@7ba zW}&R3PUGtQ*S}&Ijw25Df)ha&;Yjd>=lz*Oo?PNs9aAh1>~P*@+>MpA2QZcL!0ACQ z+qh{e)0Z3zVn%uUm)+Vm?_JdOyAT%6{NZWLpa`a19@C?$fj?6rQqS0cdKR6|i8eZh zSfZG1vK$Hp@JB3MK1k~z)xgvV{~~u{m?*Vw;zK>#eNZePA5kk!6uO(DIOeJ+35Uir zJ{rjxdz6qopl8PYl^Kkpm?{3c`^dbn?_omYUI3g-Gi0vm%>=`*HfE2f(KjVABmald z0Uby>6t&T@a6OgrAtO?m9JO?ARXa-OcD?7wIy;l6l{Q+}IwVhZXO_!Ti|xfoM+B+r z#az|;k63r%&=7x>Y6ukfV}AEEm#G;HrM@?d!eTl&mOAhpB9+i)Kg=qY~(#_5f zIQy%&O7*L^c+I$O!!v^&%C6Mr7NZ{SoigII)IEA%iQwT{c>%| zt=p*n+y27UAI0#4CnhonJ%~ZFCNTxF93D5iaD2guEXE5yoy_$5Z$3Wee&(Xhc?GKC z@5hyMYovFgPG02C`CSQ-xVv zZkgvd#t)Y<+5dyrBlL1+um|rY9KGI8GTXfTA0NAV)Dw8Ec><0HS+WEPer;l2@vsVH zS2GhWYr^v~R2eY_{_V5OSF$0vFGF7#=+A`el0!dx_FgzTeLT4Mlendt3xgADJG{P! zYe3yPW`vJq4W1W-zhg=;kJ6IR7N)O!x$I=I9xX|n0%_dCXuWjaR}7E&Dnm5Tov2MzW5 zzOZDSDS+r{(+v%*KZt>x&}R%iforDvK+$?rE@?NLvb#v{V$7vCTyD_o;PleO9%LSC zI&XHqF?NdUVi*r!`iddF*%}2KdK-OVR-WlU&Nx+PI2_M2#gn?RrlCQKc?hAh>kpcK zjc_HCKj)b0l#zR+#6bQ+4E7zaF^y3M`}Ffo@xgyF_Q@Pm986qhGCRG0XZbK?+~KS3 zVz4Kthe=O1E;Ie;1;?H+1;x9h?bw=HOp}&OEv>Gcjd|DZVEo+_0Zj|&1d_VabV-x$ z7FfiTb>)1!6d~bXEwDVmHH`)hPoZ}DtTJuwrhD?4dt6|MN);F)01y1MxXvdcc!a79B>#@u^F) z;jrlgwFldsbJP?oqFz2~`boNzkd3dIK2hrmg5&z9j8v&oMiMOXIO6Leb1|mxDROIMD2ahSl=3DNu;xcb%;gr!69H znu4I}rYXSsm))Yx_UlM=@@%B#rfHndf9st1|7Obfa$b&=8^{?Do62WW3*gUt=*E`* zVXD+dbR`G;q&COEY9CWLw5iQHV$_(AsJjk@W0H$p(wghk9t{KY5fO0tSCcoX^)}B5 z)s;+Nu`~?dDZ@J6DO(nE0g$zb3n1B1=Ay2=@`h;hbd57^#QRp(1{nUf!uo}Yp)h$7 z7Yf_Gm|np5L^j8n&Cxpc+IJVbEmNtwEhBhkDDae@c_PDHZ|{0yI1FT$m?P=`V$)6> zptblyc^MT%CY70g3U!lL$ZY)hl_{7sEHVeW2lIue*Z)bSLVlCkpWLi7rw4Y`ffF*D zTw7`O_Sg%-Uam^fP*G!wxO{O%&3s2S?5&|w$m6Tc1=j3^%nnUg$GQY0&;5xrQ zZ2m@Z3ILu0iNxom`5U$F(ogX{f5Fm>Uj_&r!Kz1aL+p42?YsV7qBj(6G98BerC5-# zGz|+HPJC||0!w%PRftFtrC4bo204L<$H!)wb zy@W!`Y^~(WJEMhC4p$bwf-an#oo2b|=Zy3TQ-kJ(R0R2MmgPvG-Lj)U6t9vrbjKYaPB^f52;*g z$y5KAvbxIoZ~PQ!n`ViImUpOuB=QBz{y^6o3-C8t za&w1ei}JoFkWcNh6a*{v+VGntoQyhRdDtSIox-S{j%LB@VXoBx=RQvKC83usvtpz= zDW^shdS7LVA}`;z43Fl%P{KT_)a6Yu>loof#AHZk$4a{e9~+$pi%F`||tNDCtlU^;X<&907@pHGo8YVC@|w zjVi2Hht0x1M`AeCU$#zH7zH}87|4Fypo2my?FW0l#E^UH6>Dp>l#mxXk!uOW5pS$Y zj3ps=tfzx>ohz%j#UYcY`U6pGe2wWmtgjZ!c5PzG0Pnq^Y9ON>I9{bHCL80~cRSs%BM4sA&xh#cY8@>8=Br)ttdQNLF^Y;Om3Fql z+w+BicQt_K(WggDza^fgqp&Bpw>yaTG%wj z)`O%@W#_7ON$nqgJ4L5bP0_&#Z`)8&j#?$As zSsC*_nS*aFbGFx&vz_#4Age0a=cI@dvCd`R@s<)xHJFc`fTfmja)J$OL^QVKp!ws2 z>W?O>RQ%6_f_li)i`nnG5N7!jHd21g-&D`a$z!oB1;UoHG#DFLIpN(=uY$4Q`a^6n z{87jDf`2!#eVuax<3=`||c13EUuz_YU$WY3tcP zyHNSS7m&-jS~Y>*K)eL)H}e`ay5 z_-#Z9c2!F)bkt%3cshS2E1~#rEow3qA5>t9wYtnvgXMbV=qqcBXF0G26fXXPj&k2r zn+dWvpmvUKWXJhr2%|z^3p+|7Y}oy_=m=gQSyU`y$2JtUu;-j?_D$^UaDl9ZLH0*% zq*I+RXM>KRu+{yYu-y?<)LT$nQ z*=f_mm;hT8d37s$QL=l|w1b`Qr7NBJ`pOw2RH_*xAnbQ`DA-qU(Js!UWea-+qFULI zPF<2-NcDFf)>vkYoAF|TH5`f#v;XQ$CPhcsQ*wxwH*k3R1RDTLUSk8vxOTROn+a|{ z&L&7YLldOQzmBsNQXojMq3m~A6RCTheOBfj`xe`s41bf=$~KB5f2jr7vcQ5K#$eKP zmTizEB9Z6V&5CYB6d=kkTuMpE3rl=2u<7!ZE$btf9fM2!R-jXOV)`d8iPU=WE0#!g zIOP5x*-TkBToOC%UCa8zxohk{l}bE$jZNT{r6XVd%mzyR0nbD9H`p5*C4T2x)KG3a)RJ8W+if@13un>^+V+ui(ShH$* zW!t*g{-k=4t*^f%&C8=~(uMwS?~bzJPZItl<4+3yq~edAygQ0h>s-Hg`(z^bh^BoH zgiYl7z>|}>{+d!P?3;{@3Qb}VgiPj=Gy~E_%Fr~t<^8P!V<|)XC58s7I{s``KbFA* z@)M+Q$t)^WzVk8u-l{GcB6cBv8n$?FVjxuBkKMmFOZhAUuHDatCdglv;pIrt*{wxN z2H`uis08_2FO@1!!Eoh{3&X`JT&A|Jy8&*j)%O;^RU7jF7q6E;ol>brE7&Urx`JPS zfHUajFN{>G2@0?-PX-Gg9Szj}y-p^@z`3bhlGgZa2kFCRLyRzAz5G>-`+UECr2~u~ z%9!=?XBsLMx_If&R`rG-J8;e~H+pNslPPhY0%=PDXVS~xUSO(0;^r4=dv{kbev=Ua z_dkHEy{nE2#q@~yXREsQQ5mKeWtTrqP^rc^k@$P7`sivI><9R@La5khP9YbkE%Y*q z(qT1w2y7|j^m@6@-CYa4!)0(Juti*`UalN>2dCt9fU%g|te1TZ@L zkMh_7d}%A4AeEcqdw|lSsvj3&3#N0{1i1p!eT&UnE5hzf=LTr}TExcu63&<)S4z51 zziO)p!`jI(IC>CgCKorlOS@~Yh{bZpZm`sWSh;A<-4cH|$76@W;AgqWcty>Z!Z?0{ zmQrpQ%q->f2~yD%dQs)>eenk0*&HYNPO2Qf{1+fiBoLW}-B5Rg+3JN+I)}Fc)lQ8P`u!5amLN z4Q4{&ftjcssWJ&Cq;!UB<6Ri+4|Apjxm?J7xc6xh>ntGB!K)9W&&;t&0 z-JnK}mhlm@xwr(mc15KcrVwk-cqdc`D`(@zJ3B=ptf|2DlIu;}H(5-f6X^$wDsZ`^ z0t`Inhbl%{P$onFUBUIxoUfD#I~}MJ{yo3l-Z8O38x&g!~*kchnkI14PBFu%cfrW?hEp_*E+zM%ngMv79d#8 zue#6A`<)K(kcH@L)EOdaM5zT4NL6Xke5)#_>=^;uR?(yy0tgSA_xb+o+h z!&(YK?&bA3@|`^bJqrpq;9GRTV>lnL27VO|0oA}gq76MNJkNyB8@Lp`6fwrAvGUIQ zPJ0I~t<4$=6_4T~Ng+!NTPneKlAw4wZmFu>R&Tf*&xVQyZtcUmo{*=8Dp6iA{xLjR z?~WA7Cm!R5X$tP=8-rj}BbSn(2vsV!6g(ipoRQ0<1UZ(7U->GqMddD7j4tMAdd-(8 z$q7>Y5Mzi_6^!|hNHAZhe;kiZMQ~7o%~&a7F;92k z)qOlx5sOh^QxA$*J}Lug%h3ZC9_1;O33A9qrJAhZX>1pHM(t%og#KaPFN%dI@`IBv za2R7*%yMx07YtkRQoyAZXeZHFSSLMOa)-s*F8*1;6Zq^#kjt}IpTOIp923AOu0jZH zmk?fkZwA_8 zL`k1`3MDlg#b@=;;8=gI!v7TH=ciCyMW8?-ZkpMh0V4?J1StZ5=lmoE!?q+PgE>Kd z?RPh%VQEUN4`4JPLKJuJ(q zp(&JBDk(ZR_Z+^Iyj1N%&R>ISoi|scq|LUm;58kC{-f8Sb;p$|2LEV*gtEa{;09^l zUMf)ri!65lB^kd=BD0Xcmg}u~f4K{#Xr3)tL|<8p=v^ztXQAu3Qq4b}aRHV$-~tPh zEMBRQr1u6Ml?3|rT!v=*F0o-+i$?I=3n=$D8x-hG`$RzEM%3!v^=J-Hy(&_4JCS9< zi^%fPD+-pTGa?}95U$cSH*H0#4`I3u5EZ7toTjzvmm}+DcUtT-jl>!MPVP zZ&dUmH%Oc8C6fkd&-iq->i%O3gdrO+{-O4hNhUbI0Yeh)0Wv8NhTX9R!GMiOF9=S8 zeRpkxU@zZV9U`>SA)p1v85J(Jp1Y6~1gl!``PY$n_9P}{!LKb`KW$LD(8`6Wn{lqo zH{pReb&Npj2mjcFS3S!kLaR5lm0=HvO47dF&_Qb7j3@o|-Ezwh25dpn?IRteLtD81 z+BYvHf%?m&K9K)*QYiG_iaqSTA&|z1qrSBjM{SKw7E$rrxGe1pLz8(SG5WKO8?L?e zbVsXhNpd$hy9Fh^dNSGdsNeEo2O{-Uau^KUg^2Ahp#>$afb{Knhras~*Hbh6Ili$_ zQ_;@c-8(Vm)@i;aYNsXB_e*^Tq@>)+Ahzs7~9c5?$YxAWlKZtV1_ z$C18mL}~Hv2m=-9tbTj<2)^OBE_c_=ee*!Y%FL+DegQfHm1k9Fbs4!{a~hzOX!59JxQQ6#^&4`J^-B_?u#*Wxu_fDB-RHiYYiwi-7D`?0)du0i1`h8n+KBPzT3dUTn0!iXHU6AvUb9aeXwqeis|-`Nmug6u*uO*tq7$1&JzuR;NIZ)r)|tAkG`coUJV!vPo%PmR-^go5B zF^Lu%ZG2-b!#A?P8iw^yf^5kV3f6BdJfKFi1)UrZ?Dhs~>K*hyeB*&wtostUHot)? zn3~FyGvUq~sK6Z@-^hTfH<6*CJ2aohCm|G0N?2y~X=Hez2T#s|WF!8sK0-fpdGZfE zd2)>goF8-D5KT#b=^6f^c7$phwVj^~NMFjV0Acr7-@(xy j7%!5Syo0v8WP;eZ_70lfr<24+>APHl&ld$8-WdN6Y_Py} delta 15638 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 G;{O55S0ar7 diff --git a/scripts/initializr/common/src/main/resources/skirmish-modules.zip b/scripts/initializr/common/src/main/resources/skirmish-modules.zip index 58e4b92ae447d70d06a892c03503276d1b2d9f54..f01c26c14ca593e3cc87657d68b5ccc6399487df 100644 GIT binary patch delta 10499 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 TzpJt<28c~fnfLH-pP2svh}K$P delta 8083 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 From f1abfe064ec954e0596f5fec912a62a0d30c45bf Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 24 Oct 2026 18:48:49 +0300 Subject: [PATCH 5/8] perf: raise the macos-arm64 translator RAM row the nightly fold set too low Co-Authored-By: Claude Opus 5.5 --- vm/selfhost/perf-baseline/pr/6094.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 vm/selfhost/perf-baseline/pr/6094.json diff --git a/vm/selfhost/perf-baseline/pr/6094.json b/vm/selfhost/perf-baseline/pr/6094.json new file mode 100644 index 00000000000..623efeb2297 --- /dev/null +++ b/vm/selfhost/perf-baseline/pr/6094.json @@ -0,0 +1,25 @@ +{ + "pr": 6094, + "rebaseline": { + "macos-arm64": { + "translator": { + "all": { + "from": { + "memory": 0.576, + "time": 0.623, + "tolerance": { + "memory": 0.35 + } + }, + "memory": 0.782, + "reason": "Nightly fold ab3505beb1 set translator all-cores RAM to 0.576 on macos-arm64; PRs with no vm/ changes measure 0.74 (#6081) and 0.79 (#6094), so the row was below the runner's normal spread", + "runs": 2, + "time": 0.623, + "tolerance": { + "memory": 0.35 + } + } + } + } + } +} From b79d558ec901e12a5949d339562cb943455642eb Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 24 Oct 2026 20:03:38 +0300 Subject: [PATCH 6/8] Samples: keep the demos on long timestamps until a release maps java.time The Initializr templates are built against the released framework, whose annotation processor rejects java.time fields. The demo conversion moves to its own pull request, for the release that includes this mapping. Co-Authored-By: Claude Opus 5.5 --- .../src/main/resources/parley-modules.zip | Bin 617266 -> 613584 bytes .../src/main/resources/savor-modules.zip | Bin 3137361 -> 3132552 bytes .../src/main/resources/skirmish-modules.zip | Bin 679147 -> 676839 bytes .../src/main/resources/wayline-modules.zip | Bin 963412 -> 960206 bytes .../com/codenameone/examples/parley/Rows.java | 13 +---- .../parley/account/AccountCleanup.java | 3 +- .../examples/parley/account/Accounts.java | 5 +- .../examples/parley/account/Moderation.java | 9 ++-- .../parley/account/PhoneVerification.java | 23 +++++---- .../examples/parley/admin/Statistics.java | 17 ++++--- .../examples/parley/bridge/Bridges.java | 9 ++-- .../examples/parley/call/Calls.java | 21 ++++---- .../examples/parley/chat/Conversations.java | 25 +++++----- .../examples/parley/chat/Fanout.java | 11 ++--- .../examples/parley/chat/Media.java | 5 +- .../examples/parley/chat/Messages.java | 19 ++++---- .../examples/parley/contact/Contacts.java | 13 +++-- .../examples/parley/device/Devices.java | 13 +++-- .../examples/parley/domain/BridgeEvent.java | 9 ++-- .../examples/parley/domain/BridgeLink.java | 7 ++- .../examples/parley/domain/CallRecord.java | 19 ++++---- .../examples/parley/domain/ClosedAccount.java | 7 ++- .../examples/parley/domain/ContactBlock.java | 7 ++- .../examples/parley/domain/Conversation.java | 13 +++-- .../parley/domain/ConversationPhoto.java | 7 ++- .../examples/parley/domain/Device.java | 13 +++-- .../examples/parley/domain/Envelope.java | 13 +++-- .../examples/parley/domain/InviteLink.java | 13 +++-- .../examples/parley/domain/LiveTicket.java | 7 ++- .../examples/parley/domain/MediaBlob.java | 7 ++- .../examples/parley/domain/Membership.java | 7 ++- .../examples/parley/domain/MessageLog.java | 7 ++- .../parley/domain/ModerationEvent.java | 7 ++- .../examples/parley/domain/PhoneCode.java | 19 ++++---- .../examples/parley/domain/Profile.java | 13 +++-- .../examples/parley/domain/ProfilePhoto.java | 7 ++- .../examples/parley/domain/PushDevice.java | 7 ++- .../examples/parley/domain/Report.java | 7 ++- .../examples/parley/live/LiveTickets.java | 7 ++- .../examples/parley/push/PushDevices.java | 5 +- .../repository/BridgeEventRepository.java | 3 +- .../repository/CallRecordRepository.java | 13 +++-- .../repository/ConversationRepository.java | 3 +- .../parley/repository/DeviceRepository.java | 3 +- .../parley/repository/EnvelopeRepository.java | 7 ++- .../repository/LiveTicketRepository.java | 3 +- .../repository/MediaBlobRepository.java | 5 +- .../repository/MessageLogRepository.java | 7 ++- .../repository/ModerationEventRepository.java | 3 +- .../parley/repository/ProfileRepository.java | 5 +- .../com/codenameone/examples/savor/Rows.java | 8 ---- .../savor/account/AccountCleanup.java | 3 +- .../examples/savor/account/Accounts.java | 5 +- .../examples/savor/account/DemoAccounts.java | 9 ++-- .../examples/savor/account/Moderation.java | 12 ++--- .../savor/account/PhoneVerification.java | 21 ++++---- .../examples/savor/admin/Statistics.java | 19 ++++---- .../examples/savor/catalog/Catalog.java | 3 +- .../savor/catalog/DemoRestaurants.java | 13 +++-- .../examples/savor/catalog/Restaurants.java | 29 ++++++----- .../examples/savor/courier/Couriers.java | 11 ++--- .../examples/savor/courier/Earnings.java | 11 ++--- .../examples/savor/delivery/Deliveries.java | 40 ++++++++-------- .../examples/savor/delivery/Matcher.java | 3 +- .../examples/savor/domain/ClosedAccount.java | 7 ++- .../savor/domain/CourierApplication.java | 19 ++++---- .../savor/domain/CourierDocument.java | 7 ++- .../examples/savor/domain/CourierState.java | 7 ++- .../examples/savor/domain/CustomerOrder.java | 31 ++++++------ .../examples/savor/domain/Delivery.java | 25 +++++----- .../savor/domain/DeliveryActivity.java | 13 +++-- .../examples/savor/domain/DeliveryEvent.java | 7 ++- .../examples/savor/domain/Favorite.java | 7 ++- .../examples/savor/domain/LiveTicket.java | 7 ++- .../savor/domain/ModerationEvent.java | 7 ++- .../examples/savor/domain/OrderEvent.java | 7 ++- .../examples/savor/domain/Payment.java | 13 +++-- .../examples/savor/domain/PaymentMethod.java | 7 ++- .../examples/savor/domain/PaymentSetup.java | 7 ++- .../examples/savor/domain/Payout.java | 7 ++- .../examples/savor/domain/PhoneCode.java | 19 ++++---- .../examples/savor/domain/Photo.java | 7 ++- .../examples/savor/domain/Pricing.java | 7 ++- .../examples/savor/domain/Profile.java | 7 ++- .../examples/savor/domain/Promo.java | 7 ++- .../examples/savor/domain/PushDevice.java | 7 ++- .../examples/savor/domain/Restaurant.java | 13 +++-- .../examples/savor/domain/SavedAddress.java | 7 ++- .../examples/savor/live/LiveTickets.java | 7 ++- .../savor/onboarding/Applications.java | 23 +++++---- .../examples/savor/order/Addresses.java | 3 +- .../examples/savor/order/DemoKitchen.java | 7 ++- .../examples/savor/order/DemoOrders.java | 27 +++++------ .../examples/savor/order/OrderEvents.java | 3 +- .../examples/savor/order/Orders.java | 30 ++++++------ .../examples/savor/order/Promos.java | 3 +- .../examples/savor/order/Quotes.java | 5 +- .../examples/savor/pay/Payments.java | 38 +++++++-------- .../examples/savor/push/OrderPushes.java | 21 ++++---- .../examples/savor/push/PushDevices.java | 5 +- .../CourierApplicationRepository.java | 7 ++- .../repository/CourierDocumentRepository.java | 3 +- .../repository/CourierStateRepository.java | 5 +- .../repository/CustomerOrderRepository.java | 35 +++++++------- .../DeliveryActivityRepository.java | 21 ++++---- .../repository/DeliveryEventRepository.java | 3 +- .../savor/repository/DeliveryRepository.java | 41 ++++++++-------- .../repository/LiveTicketRepository.java | 3 +- .../repository/ModerationEventRepository.java | 3 +- .../repository/PaymentMethodRepository.java | 3 +- .../savor/repository/PaymentRepository.java | 3 +- .../repository/PaymentSetupRepository.java | 5 +- .../savor/repository/PricingRepository.java | 3 +- .../savor/repository/ProfileRepository.java | 3 +- .../examples/skirmish/account/Accounts.java | 5 +- .../skirmish/admin/AdminEndpoint.java | 5 +- .../examples/skirmish/admin/Flags.java | 5 +- .../examples/skirmish/admin/Moderation.java | 14 +++--- .../examples/skirmish/domain/AdminAction.java | 7 ++- .../examples/skirmish/domain/Broadcast.java | 7 ++- .../examples/skirmish/domain/Flag.java | 7 ++- .../examples/skirmish/domain/ForgeAsset.java | 7 ++- .../examples/skirmish/domain/ForgePack.java | 13 +++-- .../skirmish/domain/ForgePackVersion.java | 7 ++- .../examples/skirmish/domain/GameTicket.java | 7 ++- .../examples/skirmish/domain/MatchRecord.java | 7 ++- .../skirmish/domain/MissionStars.java | 7 ++- .../examples/skirmish/domain/Pipeline.java | 7 ++- .../examples/skirmish/domain/PipelineHit.java | 7 ++- .../examples/skirmish/domain/Profile.java | 19 ++++---- .../examples/skirmish/domain/PushDevice.java | 7 ++- .../examples/skirmish/domain/Referral.java | 13 +++-- .../skirmish/domain/ReferralCode.java | 7 ++- .../examples/skirmish/domain/Spotlight.java | 7 ++- .../skirmish/domain/StorePurchase.java | 7 ++- .../examples/skirmish/forge/Forge.java | 25 +++++----- .../examples/skirmish/game/GameEndpoint.java | 4 +- .../examples/skirmish/game/GameTickets.java | 9 ++-- .../examples/skirmish/game/Results.java | 5 +- .../examples/skirmish/push/PushDevices.java | 5 +- .../repository/BroadcastRepository.java | 3 +- .../repository/ForgeAssetRepository.java | 3 +- .../repository/GameTicketRepository.java | 3 +- .../repository/MatchRecordRepository.java | 5 +- .../repository/ProfileRepository.java | 10 ++-- .../repository/StorePurchaseRepository.java | 3 +- .../examples/skirmish/shop/Shop.java | 3 +- .../examples/skirmish/social/Audience.java | 4 +- .../examples/skirmish/social/Insights.java | 21 ++++---- .../examples/skirmish/social/Pipelines.java | 13 +++-- .../examples/skirmish/social/Promotion.java | 19 ++++---- .../examples/skirmish/social/Referrals.java | 11 ++--- .../examples/wayline/account/Accounts.java | 9 ++-- .../wayline/account/DemoAccounts.java | 11 ++--- .../examples/wayline/account/Moderation.java | 14 +++--- .../wayline/account/PhoneVerification.java | 23 +++++---- .../examples/wayline/admin/Statistics.java | 35 +++++--------- .../wayline/domain/ClosedAccount.java | 7 ++- .../wayline/domain/DriverApplication.java | 19 ++++---- .../wayline/domain/DriverDocument.java | 7 ++- .../examples/wayline/domain/DriverState.java | 7 ++- .../examples/wayline/domain/LiveTicket.java | 7 ++- .../wayline/domain/ModerationEvent.java | 7 ++- .../examples/wayline/domain/Payment.java | 13 +++-- .../wayline/domain/PaymentMethod.java | 7 ++- .../examples/wayline/domain/PaymentSetup.java | 7 ++- .../examples/wayline/domain/Payout.java | 7 ++- .../examples/wayline/domain/PhoneCode.java | 19 ++++---- .../examples/wayline/domain/Pricing.java | 7 ++- .../examples/wayline/domain/Profile.java | 7 ++- .../examples/wayline/domain/PushDevice.java | 7 ++- .../examples/wayline/domain/Ride.java | 25 +++++----- .../examples/wayline/domain/RideActivity.java | 13 +++-- .../examples/wayline/domain/RideEvent.java | 7 ++- .../examples/wayline/driver/Drivers.java | 15 +++--- .../examples/wayline/driver/Earnings.java | 11 ++--- .../wayline/driving/Applications.java | 24 ++++------ .../examples/wayline/live/LiveTickets.java | 9 ++-- .../examples/wayline/pay/Payments.java | 34 +++++++------ .../examples/wayline/push/PushDevices.java | 7 ++- .../examples/wayline/push/RidePushes.java | 25 +++++----- .../DriverApplicationRepository.java | 7 ++- .../repository/DriverDocumentRepository.java | 3 +- .../repository/DriverStateRepository.java | 5 +- .../repository/LiveTicketRepository.java | 3 +- .../repository/ModerationEventRepository.java | 3 +- .../repository/PaymentMethodRepository.java | 3 +- .../wayline/repository/PaymentRepository.java | 3 +- .../repository/PaymentSetupRepository.java | 5 +- .../wayline/repository/PricingRepository.java | 3 +- .../wayline/repository/ProfileRepository.java | 3 +- .../repository/RideActivityRepository.java | 20 ++++---- .../repository/RideEventRepository.java | 3 +- .../wayline/repository/RideRepository.java | 43 ++++++++--------- .../examples/wayline/ride/DemoRides.java | 15 +++--- .../examples/wayline/ride/Fares.java | 5 +- .../examples/wayline/ride/Matcher.java | 3 +- .../examples/wayline/ride/Rides.java | 45 ++++++++---------- 198 files changed, 917 insertions(+), 1158 deletions(-) diff --git a/scripts/initializr/common/src/main/resources/parley-modules.zip b/scripts/initializr/common/src/main/resources/parley-modules.zip index 064091cef09a979d1e16b6568db72a8c77836af6..5cdfc79667b332c94edf15a97dfcb5828bcec71e 100644 GIT binary patch delta 9747 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 Q#ynfHie-P||1+5X10HYLwg3PC delta 13285 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

bo4&lo7aj+^VhwH2aZ%XRKcIM#>ZVO1X{Fv#m- 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 DX;j5T diff --git a/scripts/initializr/common/src/main/resources/savor-modules.zip b/scripts/initializr/common/src/main/resources/savor-modules.zip index c438df29fe5667cc149f08818bc408ea97c7b0ca..f66519b68a529f8c9e53c9133fff11129fa1cd96 100644 GIT binary patch delta 15638 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 G;{O55S0ar7 delta 20529 zcmbt+349dA^8X$=H#fPD&Cbs3F`Hv2;U)=?0O2MC5D+mYfovcWl8}U3LZZP3qL`pk zfC}M~+k`_JP{N@icyM?hyeB-LiWkCzry!!gnwjj(&L-=7|IeS#Cxou~R(ExEb#+fw z4a?UZS6^&DuC8xXH)(jk?Bw#=yp)#^A<~#?Z#F#%_(_jS-EJ zjZux!jWLa}jd6|fjR^?0~_ zYKtpCJ;N3Oq1l#9V%)5+)5OiJEH5dmm_Zd&Rh4BGwNzOJ#lxxM8o04suP@4=YG*oh z6#n5jjw%v+sV$<4D=0@rZCUL?YmLZITIMJ(p~`BgYDaMivZqj$)l?c)ihozkEidO= z#T5%{XX0Q|caHKJ2z!u@1jAOnx6kad^7678NZP7TXFJBB22!l^-!^Jqars<_&0brX zTU9xI<`^DM>bB~4Zt(wg;@6pXEh^Prk~TQ;b8q(<8%W%U#9LHAN3ZsZ%K32R-{yFr zZYJu;sD~2^Lv$GhIpxdhRH|ilP~UFKgr-LfesJO8L|-VH!uh}vj8fUT@@R5(g< zYHcK7UE-I6U4-wMI>eBnFROx-8?K@f&jhwulc+CqgcQ*tEx~y+4*?TW> zV?5^^31`aM?6b=%=GF-Ms$olt7uMv=sHBppA^0!*m=U8#kC*_>waF2rIo9xLVAn#< zEUqYVl#HmbkvSH_6KbQgf5l8BkS$XOb4DkJLzC6uMf9xUice&h9ANx|(nDaHArkiG z(NQFqGfWHC{j1K}t$VOa)jgQ(>u(6?tWKy(WRuB{0}ZRZeLMPvx?DqYN=JjjX;b|v z=a7ODG6k#S4cW=DH`fp+DJnOA?BL;4236sh@2IJ@SCvZ&OCOEX;raMKU?ho=_TuTa zWt9~vys6jlzl%$29o6=-njHQ&i^JK_a0MdYBjn6CM!?vihTD>`MP6n*G<{+5CH2D$ z71|)BP5(I3pi%3ddFNlA_ zhNkjF9Tb!&_F0o>_^b=t_$1FTD%fo>s=zQ*?M5qk$Z$a&;#8lY8e1k@DKt>fR%q~t z;v&O%NplJl;1!=t4IVorw{Sx4;IVl_CZM6Er=_KhhR{+&G<;QLu*Nz&cIUK_pkl*J zuSnG7AO|`QhjZ%-8#X713J34`1{2IWkfI|O90osikh3d6MhGi4M8Wk^1E-`D;|#+@ zZ_nNKfy)CE{mF%LgVtYdg!EDau5p(#jGLAiL8y6#9{qJ6UG$3@*IT6;*IV=#dmiK> z$=(BoV?LdBKNKC(TgY=q4XuG`PJ!L$PNh;~ifgCOL^~QfK6k?KLUCi-;Km>{p6a&@ zX{Ih&g-wi}y}DMgJJR-+;WO{}E}=DL71JFy*z}U#3A$y{VN8N{;|RCHLydt0aQ)djEad>HMmo& zsw+#&${jWK4wAI+3N^V-VAtn{(SeGS;Lpzu1;M(4q{#z=2dGrR17MRElLAJudde&aLpn}DDd^ zx$w|fmFl6faL!5%Cfhh_us1C3Nd+o;TY8U;A@_PxYkPL@a#{E-lS;9@)9~*y^dC0d zF@1aY#683B8e=Jy2fRuZ|Ea)f&B7El`IFCJ&TM1M-x?HvS4#zATDSn@N zLF4A4?|w)z7S|3*@4M9BH3K@jp{5BA)cp`t+yo}(O`MQBq%eQ@*!#v74jZ2{IM)XG ze^7T}zz|ZeQ#=FG z|6_`JMQfZBqTBHOx~NqdD%GkC!Do^qA;yDUxJ!yyCzG>L#vzf)Nkc%2@hi`3O>U$Z zzmIeZX;-)oag*_Xo1uNMF&cg!WIXa$M&F0OAmvPPx?ys5u|&D&i+e)McFH&wki+>ioI z-e$iwuP1pEDu})kt(*$^(?oyhKD~=cbg~i#NTNtwGM&fjde3SsjIgOx5jOGeR#(jV zlS30|=;9tA*!Rx+X?2*zxdOr(DqN}Sl?}pPObjPqm(kyL(=9vs?U$RiD%EB!|K>Ib zexJs5gVFiSc4$9C`-VMSJg?ZUczZj)gdQX9bZUBeWexvo=;Fr3i>_@c{V(ZdBCMVs z6WAe}zyikMOcX4sr<43ojk&LWd6-JIoV3-`YPF|fTN~&Py__#~)O38WsqJ#y=Evz& z#yM2Y+-bARYCQvKC$QQvuMA(Sx|+zi{mdvb@o)4bKWRFxPt*BQqh&WUL~4v`q9+AA zI~7L<;}>)koNA&|!<-LhIBLfW1Hzmy=opA>rqiV!MmEzobl$2(J2+pJit~l^!5Ap1 zUrnF#q?qhy=ouPmB6F+CD~s_xxQi9xH3P?K#*h5)9KBj2jo7f3o*>CA^24}hI+EO4 zOUHWaTGuaZJnyGco%iEC?I4)4fj;a(7Pyhm#1eKR{iAFk<;69%6C92TcLO2DO?0G} zBt*tGdW^F{R&JwLsC6l2ujxOcRH~2gm5#T}qV4o`4+E3D9kjQ<(^pbe<;BxIsz6dz z@$~7AD$llIaIO{~En4V7pOU4OILgcBIjTL5Dp~H_suB;Dn;yj!z`b8+8j8--R&sMc zy*t$ThD)Kz` zPB$jR!xqAowRAY-yh)oS(8F)ilOzc`W+;x5c9Zsnt8da4340D0c~7ibz~sT-VwnZd z8p{MiRX4^L2EIiv)lGi6Y5enXD%JCG{JRgXX({IiHQ{)Yh z&K^$u&eAiyC8bw8=FG)V$p4Sh`Ay;UnpCC2@4H(pC|!$i&`-nwV|gcF&N3QLiu3e? z0g`%7d`?f28gXCHBc+DB;)Xcy3jCT2ClO>%W%Q7AiS8#c&A8;Uu_nC-?ACsd|vs@917?4~9ej`8^#aJ4lZwhbS;f_=%n* z`$mPQuRqKTC*7{o%Od=P+iqWJ^iruBp~Z{&Rq#ro?nfnLC*uWsr#G`y3PyT9w@7ba zW}&R3PUGtQ*S}&Ijw25Df)ha&;Yjd>=lz*Oo?PNs9aAh1>~P*@+>MpA2QZcL!0ACQ z+qh{e)0Z3zVn%uUm)+Vm?_JdOyAT%6{NZWLpa`a19@C?$fj?6rQqS0cdKR6|i8eZh zSfZG1vK$Hp@JB3MK1k~z)xgvV{~~u{m?*Vw;zK>#eNZePA5kk!6uO(DIOeJ+35Uir zJ{rjxdz6qopl8PYl^Kkpm?{3c`^dbn?_omYUI3g-Gi0vm%>=`*HfE2f(KjVABmald z0Uby>6t&T@a6OgrAtO?m9JO?ARXa-OcD?7wIy;l6l{Q+}IwVhZXO_!Ti|xfoM+B+r z#az|;k63r%&=7x>Y6ukfV}AEEm#G;HrM@?d!eTl&mOAhpB9+i)Kg=qY~(#_5f zIQy%&O7*L^c+I$O!!v^&%C6Mr7NZ{SoigII)IEA%iQwT{c>%| zt=p*n+y27UAI0#4CnhonJ%~ZFCNTxF93D5iaD2guEXE5yoy_$5Z$3Wee&(Xhc?GKC z@5hyMYovFgPG02C`CSQ-xVv zZkgvd#t)Y<+5dyrBlL1+um|rY9KGI8GTXfTA0NAV)Dw8Ec><0HS+WEPer;l2@vsVH zS2GhWYr^v~R2eY_{_V5OSF$0vFGF7#=+A`el0!dx_FgzTeLT4Mlendt3xgADJG{P! zYe3yPW`vJq4W1W-zhg=;kJ6IR7N)O!x$I=I9xX|n0%_dCXuWjaR}7E&Dnm5Tov2MzW5 zzOZDSDS+r{(+v%*KZt>x&}R%iforDvK+$?rE@?NLvb#v{V$7vCTyD_o;PleO9%LSC zI&XHqF?NdUVi*r!`iddF*%}2KdK-OVR-WlU&Nx+PI2_M2#gn?RrlCQKc?hAh>kpcK zjc_HCKj)b0l#zR+#6bQ+4E7zaF^y3M`}Ffo@xgyF_Q@Pm986qhGCRG0XZbK?+~KS3 zVz4Kthe=O1E;Ie;1;?H+1;x9h?bw=HOp}&OEv>Gcjd|DZVEo+_0Zj|&1d_VabV-x$ z7FfiTb>)1!6d~bXEwDVmHH`)hPoZ}DtTJuwrhD?4dt6|MN);F)01y1MxXvdcc!a79B>#@u^F) z;jrlgwFldsbJP?oqFz2~`boNzkd3dIK2hrmg5&z9j8v&oMiMOXIO6Leb1|mxDROIMD2ahSl=3DNu;xcb%;gr!69H znu4I}rYXSsm))Yx_UlM=@@%B#rfHndf9st1|7Obfa$b&=8^{?Do62WW3*gUt=*E`* zVXD+dbR`G;q&COEY9CWLw5iQHV$_(AsJjk@W0H$p(wghk9t{KY5fO0tSCcoX^)}B5 z)s;+Nu`~?dDZ@J6DO(nE0g$zb3n1B1=Ay2=@`h;hbd57^#QRp(1{nUf!uo}Yp)h$7 z7Yf_Gm|np5L^j8n&Cxpc+IJVbEmNtwEhBhkDDae@c_PDHZ|{0yI1FT$m?P=`V$)6> zptblyc^MT%CY70g3U!lL$ZY)hl_{7sEHVeW2lIue*Z)bSLVlCkpWLi7rw4Y`ffF*D zTw7`O_Sg%-Uam^fP*G!wxO{O%&3s2S?5&|w$m6Tc1=j3^%nnUg$GQY0&;5xrQ zZ2m@Z3ILu0iNxom`5U$F(ogX{f5Fm>Uj_&r!Kz1aL+p42?YsV7qBj(6G98BerC5-# zGz|+HPJC||0!w%PRftFtrC4bo204L<$H!)wb zy@W!`Y^~(WJEMhC4p$bwf-an#oo2b|=Zy3TQ-kJ(R0R2MmgPvG-Lj)U6t9vrbjKYaPB^f52;*g z$y5KAvbxIoZ~PQ!n`ViImUpOuB=QBz{y^6o3-C8t za&w1ei}JoFkWcNh6a*{v+VGntoQyhRdDtSIox-S{j%LB@VXoBx=RQvKC83usvtpz= zDW^shdS7LVA}`;z43Fl%P{KT_)a6Yu>loof#AHZk$4a{e9~+$pi%F`||tNDCtlU^;X<&907@pHGo8YVC@|w zjVi2Hht0x1M`AeCU$#zH7zH}87|4Fypo2my?FW0l#E^UH6>Dp>l#mxXk!uOW5pS$Y zj3ps=tfzx>ohz%j#UYcY`U6pGe2wWmtgjZ!c5PzG0Pnq^Y9ON>I9{bHCL80~cRSs%BM4sA&xh#cY8@>8=Br)ttdQNLF^Y;Om3Fql z+w+BicQt_K(WggDza^fgqp&Bpw>yaTG%wj z)`O%@W#_7ON$nqgJ4L5bP0_&#Z`)8&j#?$As zSsC*_nS*aFbGFx&vz_#4Age0a=cI@dvCd`R@s<)xHJFc`fTfmja)J$OL^QVKp!ws2 z>W?O>RQ%6_f_li)i`nnG5N7!jHd21g-&D`a$z!oB1;UoHG#DFLIpN(=uY$4Q`a^6n z{87jDf`2!#eVuax<3=`||c13EUuz_YU$WY3tcP zyHNSS7m&-jS~Y>*K)eL)H}e`ay5 z_-#Z9c2!F)bkt%3cshS2E1~#rEow3qA5>t9wYtnvgXMbV=qqcBXF0G26fXXPj&k2r zn+dWvpmvUKWXJhr2%|z^3p+|7Y}oy_=m=gQSyU`y$2JtUu;-j?_D$^UaDl9ZLH0*% zq*I+RXM>KRu+{yYu-y?<)LT$nQ z*=f_mm;hT8d37s$QL=l|w1b`Qr7NBJ`pOw2RH_*xAnbQ`DA-qU(Js!UWea-+qFULI zPF<2-NcDFf)>vkYoAF|TH5`f#v;XQ$CPhcsQ*wxwH*k3R1RDTLUSk8vxOTROn+a|{ z&L&7YLldOQzmBsNQXojMq3m~A6RCTheOBfj`xe`s41bf=$~KB5f2jr7vcQ5K#$eKP zmTizEB9Z6V&5CYB6d=kkTuMpE3rl=2u<7!ZE$btf9fM2!R-jXOV)`d8iPU=WE0#!g zIOP5x*-TkBToOC%UCa8zxohk{l}bE$jZNT{r6XVd%mzyR0nbD9H`p5*C4T2x)KG3a)RJ8W+if@13un>^+V+ui(ShH$* zW!t*g{-k=4t*^f%&C8=~(uMwS?~bzJPZItl<4+3yq~edAygQ0h>s-Hg`(z^bh^BoH zgiYl7z>|}>{+d!P?3;{@3Qb}VgiPj=Gy~E_%Fr~t<^8P!V<|)XC58s7I{s``KbFA* z@)M+Q$t)^WzVk8u-l{GcB6cBv8n$?FVjxuBkKMmFOZhAUuHDatCdglv;pIrt*{wxN z2H`uis08_2FO@1!!Eoh{3&X`JT&A|Jy8&*j)%O;^RU7jF7q6E;ol>brE7&Urx`JPS zfHUajFN{>G2@0?-PX-Gg9Szj}y-p^@z`3bhlGgZa2kFCRLyRzAz5G>-`+UECr2~u~ z%9!=?XBsLMx_If&R`rG-J8;e~H+pNslPPhY0%=PDXVS~xUSO(0;^r4=dv{kbev=Ua z_dkHEy{nE2#q@~yXREsQQ5mKeWtTrqP^rc^k@$P7`sivI><9R@La5khP9YbkE%Y*q z(qT1w2y7|j^m@6@-CYa4!)0(Juti*`UalN>2dCt9fU%g|te1TZ@L zkMh_7d}%A4AeEcqdw|lSsvj3&3#N0{1i1p!eT&UnE5hzf=LTr}TExcu63&<)S4z51 zziO)p!`jI(IC>CgCKorlOS@~Yh{bZpZm`sWSh;A<-4cH|$76@W;AgqWcty>Z!Z?0{ zmQrpQ%q->f2~yD%dQs)>eenk0*&HYNPO2Qf{1+fiBoLW}-B5Rg+3JN+I)}Fc)lQ8P`u!5amLN z4Q4{&ftjcssWJ&Cq;!UB<6Ri+4|Apjxm?J7xc6xh>ntGB!K)9W&&;t&0 z-JnK}mhlm@xwr(mc15KcrVwk-cqdc`D`(@zJ3B=ptf|2DlIu;}H(5-f6X^$wDsZ`^ z0t`Inhbl%{P$onFUBUIxoUfD#I~}MJ{yo3l-Z8O38x&g!~*kchnkI14PBFu%cfrW?hEp_*E+zM%ngMv79d#8 zue#6A`<)K(kcH@L)EOdaM5zT4NL6Xke5)#_>=^;uR?(yy0tgSA_xb+o+h z!&(YK?&bA3@|`^bJqrpq;9GRTV>lnL27VO|0oA}gq76MNJkNyB8@Lp`6fwrAvGUIQ zPJ0I~t<4$=6_4T~Ng+!NTPneKlAw4wZmFu>R&Tf*&xVQyZtcUmo{*=8Dp6iA{xLjR z?~WA7Cm!R5X$tP=8-rj}BbSn(2vsV!6g(ipoRQ0<1UZ(7U->GqMddD7j4tMAdd-(8 z$q7>Y5Mzi_6^!|hNHAZhe;kiZMQ~7o%~&a7F;92k z)qOlx5sOh^QxA$*J}Lug%h3ZC9_1;O33A9qrJAhZX>1pHM(t%og#KaPFN%dI@`IBv za2R7*%yMx07YtkRQoyAZXeZHFSSLMOa)-s*F8*1;6Zq^#kjt}IpTOIp923AOu0jZH zmk?fkZwA_8 zL`k1`3MDlg#b@=;;8=gI!v7TH=ciCyMW8?-ZkpMh0V4?J1StZ5=lmoE!?q+PgE>Kd z?RPh%VQEUN4`4JPLKJuJ(q zp(&JBDk(ZR_Z+^Iyj1N%&R>ISoi|scq|LUm;58kC{-f8Sb;p$|2LEV*gtEa{;09^l zUMf)ri!65lB^kd=BD0Xcmg}u~f4K{#Xr3)tL|<8p=v^ztXQAu3Qq4b}aRHV$-~tPh zEMBRQr1u6Ml?3|rT!v=*F0o-+i$?I=3n=$D8x-hG`$RzEM%3!v^=J-Hy(&_4JCS9< zi^%fPD+-pTGa?}95U$cSH*H0#4`I3u5EZ7toTjzvmm}+DcUtT-jl>!MPVP zZ&dUmH%Oc8C6fkd&-iq->i%O3gdrO+{-O4hNhUbI0Yeh)0Wv8NhTX9R!GMiOF9=S8 zeRpkxU@zZV9U`>SA)p1v85J(Jp1Y6~1gl!``PY$n_9P}{!LKb`KW$LD(8`6Wn{lqo zH{pReb&Npj2mjcFS3S!kLaR5lm0=HvO47dF&_Qb7j3@o|-Ezwh25dpn?IRteLtD81 z+BYvHf%?m&K9K)*QYiG_iaqSTA&|z1qrSBjM{SKw7E$rrxGe1pLz8(SG5WKO8?L?e zbVsXhNpd$hy9Fh^dNSGdsNeEo2O{-Uau^KUg^2Ahp#>$afb{Knhras~*Hbh6Ili$_ zQ_;@c-8(Vm)@i;aYNsXB_e*^Tq@>)+Ahzs7~9c5?$YxAWlKZtV1_ z$C18mL}~Hv2m=-9tbTj<2)^OBE_c_=ee*!Y%FL+DegQfHm1k9Fbs4!{a~hzOX!59JxQQ6#^&4`J^-B_?u#*Wxu_fDB-RHiYYiwi-7D`?0)du0i1`h8n+KBPzT3dUTn0!iXHU6AvUb9aeXwqeis|-`Nmug6u*uO*tq7$1&JzuR;NIZ)r)|tAkG`coUJV!vPo%PmR-^go5B zF^Lu%ZG2-b!#A?P8iw^yf^5kV3f6BdJfKFi1)UrZ?Dhs~>K*hyeB*&wtostUHot)? zn3~FyGvUq~sK6Z@-^hTfH<6*CJ2aohCm|G0N?2y~X=Hez2T#s|WF!8sK0-fpdGZfE zd2)>goF8-D5KT#b=^6f^c7$phwVj^~NMFjV0Acr7-@(xy j7%!5Syo0v8WP;eZ_70lfr<24+>APHl&ld$8-WdN6Y_Py} diff --git a/scripts/initializr/common/src/main/resources/skirmish-modules.zip b/scripts/initializr/common/src/main/resources/skirmish-modules.zip index f01c26c14ca593e3cc87657d68b5ccc6399487df..58e4b92ae447d70d06a892c03503276d1b2d9f54 100644 GIT binary patch delta 8083 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 TzpJt<28c~fnfLH-pP2svh}K$P diff --git a/scripts/initializr/common/src/main/resources/wayline-modules.zip b/scripts/initializr/common/src/main/resources/wayline-modules.zip index 5df1bb7f48b5fc561f7086b2bc8d4514f6cc6775..dde1cb3a952a8598c03187c73b5c04c4352e708d 100644 GIT binary patch delta 10959 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 delta 14618 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 burWuM3$~%q7e^@Mm$pe}{ live = calls.liveOf(username, Instant.EPOCH); + List live = calls.liveOf(username); 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 897d74e3be7..b82015a1006 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,7 +40,6 @@ 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; @@ -157,7 +156,7 @@ void create(String username, String password, String displayName, String phone, profile.setDisplayName(displayName); profile.setPhone(phone); profile.setPhoneVerified(phoneVerified); - profile.setCreatedAt(Instant.ofEpochMilli(openedAt)); + profile.setCreatedAt(openedAt); profile.setLanguage(""); profiles.insert(profile); } @@ -394,7 +393,7 @@ private void retire(String username) throws IOException { if (!closed.existsById(hash)) { ClosedAccount row = new ClosedAccount(); row.setUsernameHash(hash); - row.setClosedAt(Instant.now()); + row.setClosedAt(System.currentTimeMillis()); 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 3004e49d4ab..826c2485d4d 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,7 +26,6 @@ import com.codenameone.examples.parley.repository.ModerationEventRepository; import java.io.IOException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -59,8 +58,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. - Instant newest = events.newest(username); - long after = newest == null ? 0L : newest.toEpochMilli() + 1L; + Long newest = events.newest(username); + long after = newest == null ? 0L : newest.longValue() + 1L; record(username, by, action, reason, Math.max(System.currentTimeMillis(), after)); } @@ -73,7 +72,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(Instant.ofEpochMilli(at)); + event.setCreatedAt(at); event.setActor(by); event.setAction(action); event.setReason(why.length() > 255 ? why.substring(0, 255) : why); @@ -87,7 +86,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().toEpochMilli(), row.getActor(), row.getAction(), + out.add(new ModerationEventDto(row.getCreatedAt(), 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 8af67ae0050..63106e3db47 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,7 +31,6 @@ 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. /// @@ -73,7 +72,7 @@ public PhoneChallengeDto start(String username) throws IOException { UserDto user = accounts.describe(username); String code = newCode(); String codeHash = hash(username, code); - store(username, codeHash, Instant.now()); + store(username, codeHash, System.currentTimeMillis()); try { sms.send(user.phone(), "Your Parley code is " + code); } catch (IOException failed) { @@ -99,20 +98,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, Instant now) throws IOException { + void store(String username, String codeHash, long 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 && pending.getSentAt().plusSeconds(RESEND_SECONDS).isAfter(now)) { + if (pending != null && now - pending.getSentAt() < 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().isBefore(now) && pending.getAttempts() < MAX_ATTEMPTS) { + } else if (pending.getExpiresAt() >= 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()); @@ -120,11 +119,11 @@ void store(String username, String codeHash, Instant now) throws IOException { pending.setPreviousAttempts(pending.getAttempts()); } else { pending.setPreviousHash(""); - pending.setPreviousExpiresAt(Instant.EPOCH); + pending.setPreviousExpiresAt(0L); pending.setPreviousAttempts(0); } pending.setCodeHash(codeHash); - pending.setExpiresAt(now.plusSeconds(CODE_SECONDS)); + pending.setExpiresAt(now + CODE_SECONDS * 1000L); pending.setAttempts(0); pending.setSentAt(now); if (first) { @@ -149,7 +148,7 @@ void discard(String username, String codeHash) throws IOException { return; } if (pending.getPreviousHash().length() == 0 - || pending.getPreviousExpiresAt().isBefore(Instant.now())) { + || pending.getPreviousExpiresAt() < System.currentTimeMillis()) { codes.deleteById(username); return; } @@ -157,9 +156,9 @@ void discard(String username, String codeHash) throws IOException { pending.setExpiresAt(pending.getPreviousExpiresAt()); pending.setAttempts(pending.getPreviousAttempts()); pending.setPreviousHash(""); - pending.setPreviousExpiresAt(Instant.EPOCH); + pending.setPreviousExpiresAt(0L); pending.setPreviousAttempts(0); - pending.setSentAt(Instant.EPOCH); + pending.setSentAt(0L); } /// Checks the code the user typed. Answers 400 for a wrong or expired one @@ -187,7 +186,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().isBefore(Instant.now())) { + if (pending == null || pending.getExpiresAt() < System.currentTimeMillis()) { throw new ResponseStatusException(400, "That code has expired. Ask for a new one"); } if (pending.getAttempts() >= MAX_ATTEMPTS) { @@ -223,7 +222,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().isBefore(Instant.now()) + && pending.getPreviousExpiresAt() >= System.currentTimeMillis() && 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 3530fd69057..37106cf12a8 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,7 +40,6 @@ 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; @@ -94,8 +93,8 @@ public AdminStatsDto dashboard() throws IOException { (int) conversations.count(), (int) (conversations.countByKind(Conversations.GROUP) + conversations.countByKind(Conversations.CHANNEL)), - (int) messages.countBySentAtGreaterThanEqual(Instant.ofEpochMilli(today)), - (int) calls.countByStartedAtGreaterThanEqual(Instant.ofEpochMilli(today)), + (int) messages.countBySentAtGreaterThanEqual(today), + (int) calls.countByStartedAtGreaterThanEqual(today), (int) reports.countByStatus(OPEN), (int) bridges.count()); } @@ -114,8 +113,8 @@ public StatsSeriesDto series(int days) throws IOException { active.add(new HashSet<>()); } int[] byHour = new int[24]; - for (Object[] row : messages.since(Instant.ofEpochMilli(since))) { - long at = Rows.millis(row[0]); + for (Object[] row : messages.since(since)) { + long at = Rows.number(row[0]); byHour[(int) (at % Days.MILLIS / 3600000L)]++; int index = index(at, since, span); if (index >= 0) { @@ -123,14 +122,14 @@ public StatsSeriesDto series(int days) throws IOException { active.get(index).add(Rows.text(row[1])); } } - for (Instant at : calls.startedSince(Instant.ofEpochMilli(since))) { - int index = index(Rows.millis(at), since, span); + for (Long at : calls.startedSince(since)) { + int index = index(Rows.number(at), since, span); if (index >= 0) { dayCalls[index]++; } } - for (Instant at : profiles.signUps(Instant.ofEpochMilli(since))) { - int index = index(Rows.millis(at), since, span); + for (Long at : profiles.signUps(since)) { + int index = index(Rows.number(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 e592d2c6468..8e1369fdebf 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,7 +39,6 @@ import com.codenameone.examples.parley.repository.MembershipRepository; import java.io.IOException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -135,7 +134,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(Instant.now()); + link.setCreatedAt(System.currentTimeMillis()); 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."); @@ -175,8 +174,8 @@ public void incoming(String network, String externalChat, String senderName, Str return; } long now = System.currentTimeMillis(); - events.deleteByReceivedAtLessThan(Instant.ofEpochMilli(now - EVENT_MEMORY_MILLIS)); - events.insert(new BridgeEvent(key, Instant.ofEpochMilli(now))); + events.deleteByReceivedAtLessThan(now - EVENT_MEMORY_MILLIS); + events.insert(new BridgeEvent(key, now)); } BridgeLink link = links.findByNetworkAndExternalChat(network, externalChat); if (link == null) { @@ -233,6 +232,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().toEpochMilli()); + row.getExternalChat(), row.getLabel(), row.getCreatedAt()); } } 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 f22939baf1a..27dee836f85 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,7 +52,6 @@ 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; @@ -174,11 +173,11 @@ public CallDto start(String username, CallStartDto request, boolean busy) throws row.setCallee(callee); row.setCalleeDevice(""); row.setVideo(request.video()); - row.setStartedAt(Instant.ofEpochMilli(now)); + row.setStartedAt(now); boolean blocked = blocked(username, callee); if (busy || lines.findById(callee) != null) { row.setState(BUSY); - row.setEndedAt(Instant.ofEpochMilli(now)); + row.setEndedAt(now); } else { row.setState(RINGING); } @@ -236,7 +235,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, Instant.EPOCH)) { + for (CallRecord row : calls.liveOf(username)) { if (username.equals(row.getCallee()) && RINGING.equals(row.getState()) && !blocked(row.getCaller(), row.getCallee())) { live.toDevice(device, frame(row, "ring")); @@ -263,7 +262,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().equals(Instant.EPOCH)) { + if (row.getEndedAt() != 0) { // A late candidate for a call that is over is not an error the // app can do anything about. return toDto(row); @@ -292,7 +291,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(Instant.ofEpochMilli(now)); + row.setAnsweredAt(now); row.setCalleeDevice(device); // The callee's other devices are still ringing. String ringId = uuid(row.getId()); @@ -378,14 +377,14 @@ public IceConfigDto ice(String username) { @Transactional(rollbackFor = IOException.class) public void reap() throws IOException { long now = System.currentTimeMillis(); - for (CallRecord row : calls.openSince(Instant.ofEpochMilli(now - RING_MILLIS), Instant.EPOCH)) { + for (CallRecord row : calls.openSince(now - RING_MILLIS)) { 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().toEpochMilli() < now - STALE_MILLIS) { + } else if (row.getAnsweredAt() < 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. @@ -450,7 +449,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(Instant.ofEpochMilli(now)); + row.setEndedAt(now); lines.deleteByCallId(row.getId()); if (setups.findById(row.getId()) != null) { setups.deleteById(row.getId()); @@ -549,7 +548,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().toEpochMilli(), - row.getAnsweredAt().toEpochMilli(), row.getEndedAt().toEpochMilli(), uuid(row.getId())); + row.getCallee(), row.isVideo(), row.getState(), row.getStartedAt(), + row.getAnsweredAt(), row.getEndedAt(), 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 f5dcea7ae50..7df3428193e 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,7 +51,6 @@ 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; @@ -427,7 +426,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().isBefore(heir.getJoinedAt())) { + || rank(each) == rank(heir) && each.getJoinedAt() < heir.getJoinedAt()) { heir = each; } } @@ -463,8 +462,8 @@ public InviteDto invite(String username, String id) throws IOException { link.setCode(Ids.next()); link.setConversationId(id); link.setCreatedBy(username); - link.setCreatedAt(Instant.ofEpochMilli(now)); - link.setExpiresAt(Instant.ofEpochMilli(now + INVITE_LIFE)); + link.setCreatedAt(now); + link.setExpiresAt(now + INVITE_LIFE); invites.insert(link); return toDto(link, row, members.countByConversationId(id)); } @@ -497,8 +496,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().isAfter(Instant.EPOCH) - && link.getExpiresAt().isBefore(Instant.now())) { + if (link == null || link.getExpiresAt() > 0 + && link.getExpiresAt() < System.currentTimeMillis()) { throw new ResponseStatusException(404, "That invite link does not work any more"); } return link; @@ -520,12 +519,12 @@ public ConversationDto savePhoto(String username, String id, PhotoDto photo) stored = new ConversationPhoto(); stored.setConversationId(id); stored.setContentType(photo.contentType()); - stored.setUpdatedAt(Instant.now()); + stored.setUpdatedAt(System.currentTimeMillis()); stored.setData(data); photos.insert(stored); } else { stored.setContentType(photo.contentType()); - stored.setUpdatedAt(Instant.now()); + stored.setUpdatedAt(System.currentTimeMillis()); stored.setData(data); } row.setHasPhoto(true); @@ -560,8 +559,8 @@ private static Conversation conversation(String kind, String title, String by, l row.setKind(kind); row.setTitle(title); row.setCreatedBy(by); - row.setCreatedAt(Instant.ofEpochMilli(now)); - row.setLastActivityAt(Instant.ofEpochMilli(now)); + row.setCreatedAt(now); + row.setLastActivityAt(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 @@ -576,7 +575,7 @@ private void join(String id, String username, String role, long now) { row.setConversationId(id); row.setUsername(username); row.setRole(role); - row.setJoinedAt(Instant.ofEpochMilli(now)); + row.setJoinedAt(now); members.insert(row); } @@ -684,11 +683,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().toEpochMilli(), row.isHasPhoto()); + row.getLastActivityAt(), 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().toEpochMilli()); + link.getExpiresAt()); } } 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 628cb1d7694..b446c6a3c51 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,7 +35,6 @@ 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; @@ -177,8 +176,8 @@ static Envelope envelope(String messageId, String conversationId, String sender, row.setKind(kind); row.setHeader(header == null ? "" : header); row.setPayload(payload); - row.setSentAt(Instant.ofEpochMilli(sentAt)); - row.setExpiresAt(Instant.ofEpochMilli(expiresAt)); + row.setSentAt(sentAt); + row.setExpiresAt(expiresAt); return row; } @@ -195,8 +194,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().toEpochMilli())); - frame.put("expiresAt", Long.valueOf(row.getExpiresAt().toEpochMilli())); + frame.put("sentAt", Long.valueOf(row.getSentAt())); + frame.put("expiresAt", Long.valueOf(row.getExpiresAt())); live.toDevice(row.getRecipientDevice(), frame); } } @@ -204,6 +203,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().toEpochMilli(), row.getExpiresAt().toEpochMilli()); + Base64.encode(row.getPayload()), row.getSentAt(), row.getExpiresAt()); } } 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 f59ada5dae9..2bf509e5020 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,7 +30,6 @@ import com.codenameone.examples.parley.repository.MediaBlobRepository; import java.io.IOException; -import java.time.Instant; /// Encrypted attachments. /// @@ -69,7 +68,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, Instant.ofEpochMilli(now - DAY_MILLIS)); + Long stored = blobs.storedSince(username, now - DAY_MILLIS); if ((stored == null ? 0L : stored.longValue()) + data.length > DAILY_BYTES) { throw new ResponseStatusException(429, "You have uploaded too much today"); } @@ -77,7 +76,7 @@ public MediaRefDto upload(String username, MediaUploadDto media) throws IOExcept row.setId(Ids.next()); row.setOwner(username); row.setSize(data.length); - row.setCreatedAt(Instant.ofEpochMilli(now)); + row.setCreatedAt(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 bfc63f12ce1..c7e0a90bcef 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,7 +49,6 @@ 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; @@ -152,7 +151,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().toEpochMilli(), + return new SendResultDto(seen.getMessageId(), seen.getSentAt(), new ArrayList(), new ArrayList()); } } @@ -237,7 +236,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, Instant.ofEpochMilli(now)); + conversationRows.touched(id, now); } return new SendResultDto(messageId, now, missing, stale); } @@ -259,7 +258,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(), Instant.ofEpochMilli(now)); + conversationRows.touched(row.getId(), now); Profile profile = profiles.findById(username); relays.posted(row.getId(), username, profile == null ? username : profile.getDisplayName(), text); @@ -279,7 +278,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, Instant.ofEpochMilli(now)); + conversationRows.touched(conversationId, now); return messageId; } @@ -315,10 +314,10 @@ public KeyCountDto ack(String username, String device, AckDto ack) { @Transactional public void reap() { long now = System.currentTimeMillis(); - 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)); + envelopes.expire(now); + envelopes.deleteBySentAtLessThan(now - UNCLAIMED); + media.deleteByCreatedAtLessThan(now - UNCLAIMED); + log.deleteBySentAtLessThan(now - 90L * 24 * 60 * 60 * 1000); } private void record(String logId, String messageId, String conversationId, String sender, @@ -332,7 +331,7 @@ private void record(String logId, String messageId, String conversationId, Strin row.setConversationId(conversationId); row.setSender(sender); row.setKind(kind); - row.setSentAt(Instant.ofEpochMilli(now)); + row.setSentAt(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 c17bdd6739f..5330ec1106a 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,7 +45,6 @@ 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; @@ -147,7 +146,7 @@ public ContactDto block(String viewer, String username) throws IOException { row.setId(id); row.setBlocker(viewer); row.setBlocked(username); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); blocks.insert(row); } return view(viewer, profile, peers(viewer)); @@ -186,7 +185,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(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); row.setStatus("OPEN"); reports.insert(row); java.util.Map frame = new java.util.LinkedHashMap(); @@ -218,7 +217,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().toEpochMilli(), + row.getConversationId(), row.getReason(), row.getEvidence(), row.getCreatedAt(), row.getStatus()); } @@ -236,12 +235,12 @@ public void savePhoto(String username, PhotoDto photo) throws IOException { row = new ProfilePhoto(); row.setUsername(username); row.setContentType(photo.contentType()); - row.setUpdatedAt(Instant.now()); + row.setUpdatedAt(System.currentTimeMillis()); row.setData(data); photos.insert(row); } else { row.setContentType(photo.contentType()); - row.setUpdatedAt(Instant.now()); + row.setUpdatedAt(System.currentTimeMillis()); row.setData(data); } profile.setHasPhoto(true); @@ -269,7 +268,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().toEpochMilli(); + lastSeen = live.online(username) ? -1L : profile.getLastSeenAt(); } 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 6862616a0c3..a8dfbc75a8d 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,7 +41,6 @@ import com.codenameone.examples.parley.repository.ProfileRepository; import java.io.IOException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -110,8 +109,8 @@ public DeviceDto register(String username, DeviceRegistrationDto request) throws row.setSignedPreKeyId(signed.id()); row.setSignedPreKey(signed.publicKey()); row.setSignedPreKeySignature(signed.signature()); - row.setCreatedAt(Instant.ofEpochMilli(now)); - row.setLastSeenAt(Instant.ofEpochMilli(now)); + row.setCreatedAt(now); + row.setLastSeenAt(now); devices.insert(row); store(row.getId(), request.oneTimePreKeys()); return toDto(row); @@ -198,8 +197,8 @@ public boolean owns(String username, String device) { @Transactional public void seen(String username, String device) { long now = System.currentTimeMillis(); - devices.seen(device, Instant.ofEpochMilli(now)); - profiles.seen(username, Instant.ofEpochMilli(now)); + devices.seen(device, now); + profiles.seen(username, now); } /// The device, or a 404 when it is not the caller's: a device of somebody @@ -297,7 +296,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().toEpochMilli(), - row.getLastSeenAt().toEpochMilli()); + return new DeviceDto(row.getId(), row.getName(), row.getPlatform(), row.getCreatedAt(), + row.getLastSeenAt()); } } 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 8fdc22847f1..af3e1c5e5d4 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,7 +21,6 @@ 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 @@ -33,12 +32,12 @@ public class BridgeEvent { private String id = ""; @Column(nullable = false) - private Instant receivedAt = Instant.EPOCH; + private long receivedAt; public BridgeEvent() { } - public BridgeEvent(String id, Instant receivedAt) { + public BridgeEvent(String id, long receivedAt) { this.id = id; this.receivedAt = receivedAt; } @@ -51,11 +50,11 @@ public void setId(String id) { this.id = id; } - public Instant getReceivedAt() { + public long getReceivedAt() { return receivedAt; } - public void setReceivedAt(Instant receivedAt) { + public void setReceivedAt(long 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 79737385bf6..766ad68ecb6 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,7 +21,6 @@ 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 @@ -46,7 +45,7 @@ public class BridgeLink { private String createdBy = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public BridgeLink() { } @@ -99,11 +98,11 @@ public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 2a86dfb3be8..a46ab855659 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,7 +21,6 @@ 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 @@ -52,13 +51,13 @@ public class CallRecord { private String state = ""; @Column(nullable = false) - private Instant startedAt = Instant.EPOCH; + private long startedAt; @Column(nullable = false) - private Instant answeredAt = Instant.EPOCH; + private long answeredAt; @Column(nullable = false) - private Instant endedAt = Instant.EPOCH; + private long endedAt; public CallRecord() { } @@ -127,27 +126,27 @@ public void setState(String state) { this.state = state; } - public Instant getStartedAt() { + public long getStartedAt() { return startedAt; } - public void setStartedAt(Instant startedAt) { + public void setStartedAt(long startedAt) { this.startedAt = startedAt; } - public Instant getAnsweredAt() { + public long getAnsweredAt() { return answeredAt; } - public void setAnsweredAt(Instant answeredAt) { + public void setAnsweredAt(long answeredAt) { this.answeredAt = answeredAt; } - public Instant getEndedAt() { + public long getEndedAt() { return endedAt; } - public void setEndedAt(Instant endedAt) { + public void setEndedAt(long 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 fe2a48f48da..218bcca199d 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,7 +21,6 @@ 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. @@ -32,7 +31,7 @@ public class ClosedAccount { private String usernameHash = ""; @Column(nullable = false) - private Instant closedAt = Instant.EPOCH; + private long closedAt; public ClosedAccount() { } @@ -45,11 +44,11 @@ public void setUsernameHash(String usernameHash) { this.usernameHash = usernameHash; } - public Instant getClosedAt() { + public long getClosedAt() { return closedAt; } - public void setClosedAt(Instant closedAt) { + public void setClosedAt(long 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 7530dcda457..d724142d9cd 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,7 +21,6 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; -import java.time.Instant; /// One account blocking another. @Entity @@ -37,7 +36,7 @@ public class ContactBlock { private String blocked = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public ContactBlock() { } @@ -66,11 +65,11 @@ public void setBlocked(String blocked) { this.blocked = blocked; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 c3b0492f6e3..fe392c733ed 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,7 +21,6 @@ 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 @@ -52,10 +51,10 @@ public class Conversation { private String createdBy = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) - private Instant lastActivityAt = Instant.EPOCH; + private long lastActivityAt; @Column(nullable = false, type = "VARCHAR(400)") private String directKey = ""; @@ -127,19 +126,19 @@ public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } - public Instant getLastActivityAt() { + public long getLastActivityAt() { return lastActivityAt; } - public void setLastActivityAt(Instant lastActivityAt) { + public void setLastActivityAt(long 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 585299d0207..42fd1c7283b 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,7 +21,6 @@ import com.codename1.annotations.Column; import com.codename1.annotations.Entity; import com.codename1.annotations.Id; -import java.time.Instant; /// A group's photo. @Entity @@ -34,7 +33,7 @@ public class ConversationPhoto { private String contentType = ""; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; @Column(nullable = false) private byte[] data = new byte[0]; @@ -58,11 +57,11 @@ public void setContentType(String contentType) { this.contentType = contentType; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 da2a9fa2240..b5ef39ad02b 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,7 +21,6 @@ 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 @@ -54,10 +53,10 @@ public class Device { private String signedPreKeySignature = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) - private Instant lastSeenAt = Instant.EPOCH; + private long lastSeenAt; public Device() { } @@ -126,19 +125,19 @@ public void setSignedPreKeySignature(String signedPreKeySignature) { this.signedPreKeySignature = signedPreKeySignature; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } - public Instant getLastSeenAt() { + public long getLastSeenAt() { return lastSeenAt; } - public void setLastSeenAt(Instant lastSeenAt) { + public void setLastSeenAt(long 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 a7c11c43ae5..f0ff74365fc 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,7 +21,6 @@ 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 @@ -60,10 +59,10 @@ public class Envelope { private byte[] payload = new byte[0]; @Column(nullable = false) - private Instant sentAt = Instant.EPOCH; + private long sentAt; @Column(nullable = false) - private Instant expiresAt = Instant.EPOCH; + private long expiresAt; public Envelope() { } @@ -148,19 +147,19 @@ public void setPayload(byte[] payload) { this.payload = payload; } - public Instant getSentAt() { + public long getSentAt() { return sentAt; } - public void setSentAt(Instant sentAt) { + public void setSentAt(long sentAt) { this.sentAt = sentAt; } - public Instant getExpiresAt() { + public long getExpiresAt() { return expiresAt; } - public void setExpiresAt(Instant expiresAt) { + public void setExpiresAt(long 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 77f49fb3036..de7fa5c6e95 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,7 +21,6 @@ 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 @@ -37,10 +36,10 @@ public class InviteLink { private String createdBy = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) - private Instant expiresAt = Instant.EPOCH; + private long expiresAt; public InviteLink() { } @@ -69,19 +68,19 @@ public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } - public Instant getExpiresAt() { + public long getExpiresAt() { return expiresAt; } - public void setExpiresAt(Instant expiresAt) { + public void setExpiresAt(long 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 bcc13b8b614..4d4f5ce392f 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,7 +21,6 @@ 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 @@ -34,7 +33,7 @@ public class LiveTicket { private String username = ""; @Column(nullable = false) - private Instant expiresAt = Instant.EPOCH; + private long expiresAt; public LiveTicket() { } @@ -55,11 +54,11 @@ public void setUsername(String username) { this.username = username; } - public Instant getExpiresAt() { + public long getExpiresAt() { return expiresAt; } - public void setExpiresAt(Instant expiresAt) { + public void setExpiresAt(long 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 a025c07fb59..78c7fa4154c 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,7 +21,6 @@ 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 @@ -37,7 +36,7 @@ public class MediaBlob { private int size; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) private byte[] data = new byte[0]; @@ -69,11 +68,11 @@ public void setSize(int size) { this.size = size; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 a9178067f42..f4b5e9aab52 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,7 +21,6 @@ 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 @@ -49,7 +48,7 @@ public class Membership { private boolean pinned; @Column(nullable = false) - private Instant joinedAt = Instant.EPOCH; + private long joinedAt; public Membership() { } @@ -110,11 +109,11 @@ public void setPinned(boolean pinned) { this.pinned = pinned; } - public Instant getJoinedAt() { + public long getJoinedAt() { return joinedAt; } - public void setJoinedAt(Instant joinedAt) { + public void setJoinedAt(long 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 4e2d8b39705..beee8559cde 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,7 +21,6 @@ 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. @@ -44,7 +43,7 @@ public class MessageLog { private String kind = ""; @Column(nullable = false) - private Instant sentAt = Instant.EPOCH; + private long sentAt; public MessageLog() { } @@ -89,11 +88,11 @@ public void setKind(String kind) { this.kind = kind; } - public Instant getSentAt() { + public long getSentAt() { return sentAt; } - public void setSentAt(Instant sentAt) { + public void setSentAt(long 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 17ad2945e5b..49fe0e5d86f 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,7 +21,6 @@ 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 @@ -34,7 +33,7 @@ public class ModerationEvent { private String username = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(190)") private String actor = ""; @@ -64,11 +63,11 @@ public void setUsername(String username) { this.username = username; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 b401b05eb4e..4084d725165 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,7 +21,6 @@ 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 @@ -34,20 +33,20 @@ public class PhoneCode { private String codeHash = ""; @Column(nullable = false) - private Instant expiresAt = Instant.EPOCH; + private long expiresAt; @Column(nullable = false) private int attempts; @Column(nullable = false) - private Instant sentAt = Instant.EPOCH; + private long sentAt; /// 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 Instant previousExpiresAt = Instant.EPOCH; + private long previousExpiresAt; /// 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. @@ -73,11 +72,11 @@ public void setCodeHash(String codeHash) { this.codeHash = codeHash; } - public Instant getExpiresAt() { + public long getExpiresAt() { return expiresAt; } - public void setExpiresAt(Instant expiresAt) { + public void setExpiresAt(long expiresAt) { this.expiresAt = expiresAt; } @@ -89,11 +88,11 @@ public void setAttempts(int attempts) { this.attempts = attempts; } - public Instant getSentAt() { + public long getSentAt() { return sentAt; } - public void setSentAt(Instant sentAt) { + public void setSentAt(long sentAt) { this.sentAt = sentAt; } @@ -105,11 +104,11 @@ public void setPreviousHash(String previousHash) { this.previousHash = previousHash; } - public Instant getPreviousExpiresAt() { + public long getPreviousExpiresAt() { return previousExpiresAt; } - public void setPreviousExpiresAt(Instant previousExpiresAt) { + public void setPreviousExpiresAt(long 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 40dcc9b1bb5..d0412fa68c5 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,7 +21,6 @@ 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. /// @@ -49,10 +48,10 @@ public class Profile { private boolean hasPhoto; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) - private Instant lastSeenAt = Instant.EPOCH; + private long lastSeenAt; @Column(nullable = false, type = "VARCHAR(8)") private String language = ""; @@ -114,19 +113,19 @@ public void setHasPhoto(boolean hasPhoto) { this.hasPhoto = hasPhoto; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } - public Instant getLastSeenAt() { + public long getLastSeenAt() { return lastSeenAt; } - public void setLastSeenAt(Instant lastSeenAt) { + public void setLastSeenAt(long 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 50289ca95c2..7853aaba4f5 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,7 +21,6 @@ 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 @@ -34,7 +33,7 @@ public class ProfilePhoto { private String contentType = ""; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; @Column(nullable = false) private byte[] data = new byte[0]; @@ -58,11 +57,11 @@ public void setContentType(String contentType) { this.contentType = contentType; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 7e2d1dbf673..8c5377843d2 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,7 +21,6 @@ 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. /// @@ -47,7 +46,7 @@ public class PushDevice { private String platform = ""; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; public PushDevice() { } @@ -92,11 +91,11 @@ public void setPlatform(String platform) { this.platform = platform; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 2d4cc27c840..784c72f5341 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,7 +21,6 @@ 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 @@ -46,7 +45,7 @@ public class Report { private String evidence = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(16)") private String status = ""; @@ -108,11 +107,11 @@ public void setEvidence(String evidence) { this.evidence = evidence; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 1fda517193f..685412bed0f 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,7 +28,6 @@ import com.codenameone.examples.parley.repository.LiveTicketRepository; import java.io.IOException; -import java.time.Instant; /// Tickets for the live channel. /// @@ -59,7 +58,7 @@ public TicketDto issue(String username) throws IOException { LiveTicket row = new LiveTicket(); row.setTicketHash(Ids.sha256(ticket)); row.setUsername(username); - row.setExpiresAt(Instant.now().plusSeconds(TICKET_SECONDS)); + row.setExpiresAt(System.currentTimeMillis() + TICKET_SECONDS * 1000L); tickets.insert(row); return new TicketDto(ticket, TICKET_SECONDS); } @@ -79,7 +78,7 @@ public String redeem(String ticket) throws IOException { return null; } String username = row.getUsername(); - long expiresAt = row.getExpiresAt().toEpochMilli(); + long 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); @@ -93,7 +92,7 @@ public String redeem(String ticket) throws IOException { @Scheduled(fixedDelay = 60000, initialDelay = 60000) @Transactional public void sweep() throws IOException { - tickets.deleteByExpiresAtLessThan(Instant.now()); + tickets.deleteByExpiresAtLessThan(System.currentTimeMillis()); } /// 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 84aea8499e5..7cb6d50afc1 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,7 +30,6 @@ import com.codenameone.examples.parley.repository.PushDeviceRepository; import java.io.IOException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -116,7 +115,7 @@ private void makeRoom(String username) { while (held.size() >= MAX_PER_ACCOUNT) { PushDevice oldest = held.get(0); for (PushDevice each : held) { - if (each.getUpdatedAt().isBefore(oldest.getUpdatedAt())) { + if (each.getUpdatedAt() < oldest.getUpdatedAt()) { oldest = each; } } @@ -169,7 +168,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(Instant.ofEpochMilli(now)); + row.setUpdatedAt(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 47cd4578f6f..3188205f617 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,10 +21,9 @@ 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(Instant before); + int deleteByReceivedAtLessThan(long 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 c7eafc30338..f993ecd4e05 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,7 +25,6 @@ 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. @@ -43,16 +42,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 = :none") - List liveOf(@Param("username") String username, @Param("none") Instant none); + @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.endedAt = :none and c.startedAt < :before") - List openSince(@Param("before") Instant before, @Param("none") Instant none); + @Query("select c from CallRecord c where c.endedAt = 0 and c.startedAt < :before") + List openSince(@Param("before") long before); - long countByStartedAtGreaterThanEqual(Instant since); + long countByStartedAtGreaterThanEqual(long since); @Query("select c.startedAt from CallRecord c where c.startedAt >= :since") - List startedSince(@Param("since") Instant since); + List startedSince(@Param("since") long 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 b91dcea7e89..81ed407f776 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,7 +25,6 @@ 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. @@ -49,5 +48,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") Instant at); + int seen(@Param("id") String id, @Param("at") long 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 8b9e7b16e14..e48afdf5652 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,7 +25,6 @@ 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. @@ -46,9 +45,9 @@ public interface EnvelopeRepository extends CrudRepository { /// Removes what the disappearing timer has run out on. @Modifying - @Query("delete from Envelope e where e.expiresAt > :none and e.expiresAt <= :now") - int expire(@Param("now") Instant now, @Param("none") Instant none); + @Query("delete from Envelope e where e.expiresAt > 0 and e.expiresAt <= :now") + int expire(@Param("now") long now); /// Removes what nobody fetched for a month: the device is gone or lost. - int deleteBySentAtLessThan(Instant before); + int deleteBySentAtLessThan(long 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 4bb95fd8253..f8f8857177b 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,7 +21,6 @@ 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. @@ -34,7 +33,7 @@ public interface LiveTicketRepository extends CrudRepository int deleteByTicketHash(String ticketHash); /// Deletes the tickets that went stale before `now`. - int deleteByExpiresAtLessThan(Instant now); + int deleteByExpiresAtLessThan(long 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 76e0471caf0..db2dc77aca2 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,15 +23,14 @@ 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(Instant before); + int deleteByCreatedAtLessThan(long 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") Instant since); + Long storedSince(@Param("owner") String owner, @Param("since") long 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 f0d87a050e2..4667c1949ba 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,20 +24,19 @@ 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(Instant since); + long countBySentAtGreaterThanEqual(long 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") Instant since); + List since(@Param("since") long since); int deleteBySender(String sender); - int deleteBySentAtLessThan(Instant before); + int deleteBySentAtLessThan(long 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 38ecf943b74..ee2385462bd 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,7 +24,6 @@ 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. @@ -33,7 +32,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 a94031b9ca2..cfbaa34aee4 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,7 +25,6 @@ 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. @@ -62,9 +61,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") Instant since); + List signUps(@Param("since") long since); @Modifying @Query("update Profile p set p.lastSeenAt = :at where p.username = :username") - int seen(@Param("username") String username, @Param("at") Instant at); + int seen(@Param("username") String username, @Param("at") long 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 40bef0bb2e1..6c84eae362d 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,7 +21,6 @@ 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; @@ -42,13 +41,6 @@ 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 aa2f296d130..ecac220794f 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,7 +39,6 @@ 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 @@ -206,7 +205,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(Instant.now()); + restaurant.setUpdatedAt(System.currentTimeMillis()); } } 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 8994ab9d3f9..d761c97ad69 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,7 +43,6 @@ 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; @@ -185,7 +184,7 @@ void create(String username, String password, String displayName, String phone, profile.setPhoneVerified(phoneVerified); profile.setVehicle(vehicle); profile.setPlate(plate); - profile.setCreatedAt(Instant.ofEpochMilli(openedAt)); + profile.setCreatedAt(openedAt); profiles.insert(profile); if (courier) { applications.grant(username, username); @@ -518,7 +517,7 @@ private void retire(String username) throws IOException { if (!closed.existsById(hash)) { ClosedAccount row = new ClosedAccount(); row.setUsernameHash(hash); - row.setClosedAt(Instant.now()); + row.setClosedAt(System.currentTimeMillis()); 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 d3a0fffd763..24fc43cac8e 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,7 +40,6 @@ import com.codenameone.examples.savor.order.DemoOrders; import java.io.IOException; -import java.time.Instant; /// The accounts a server starts with. /// @@ -171,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, - Instant.now().minusMillis(daysAgo * Days.MILLIS)); + System.currentTimeMillis() - daysAgo * Days.MILLIS); } /// An admin, or the plainest kind of account. @@ -241,7 +240,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(Instant.ofEpochMilli(handedIn)); + form.setSubmittedAt(handedIn); form.setReviewedBy(ADMIN); for (int iter = 0; iter < Applications.KINDS.length; iter++) { CourierDocument picture = new CourierDocument(); @@ -249,7 +248,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(Instant.ofEpochMilli(handedIn)); + picture.setUploadedAt(handedIn); picture.setData(PLACEHOLDER_PICTURE); documents.insert(picture); } @@ -285,7 +284,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(Instant.ofEpochMilli(System.currentTimeMillis() - daysAgo * Days.MILLIS)); + form.setSubmittedAt(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 85db0b83e34..24ab4f8f2dc 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,7 +26,6 @@ import com.codenameone.examples.savor.repository.ModerationEventRepository; import java.io.IOException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -61,16 +60,15 @@ 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. - 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); + Long newest = events.newest(username); + long after = newest == null ? 0L : newest.longValue() + 1L; + record(username, by, action, reason, Math.max(System.currentTimeMillis(), after)); } /// 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, Instant at) + public void record(String username, String by, String action, String reason, long at) throws IOException { String why = reason == null ? "" : reason.trim(); ModerationEvent event = new ModerationEvent(); @@ -90,7 +88,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().toEpochMilli(), row.getActor(), row.getAction(), + out.add(new ModerationEventDto(row.getCreatedAt(), 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 92f869eb193..cb85edf4f8e 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,7 +31,6 @@ 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. /// @@ -105,14 +104,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().toEpochMilli() < RESEND_SECONDS * 1000L) { + if (pending != null && now - pending.getSentAt() < 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().toEpochMilli() >= now && pending.getAttempts() < MAX_ATTEMPTS) { + } else if (pending.getExpiresAt() >= 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()); @@ -120,13 +119,13 @@ void store(String username, String codeHash, long now) throws IOException { pending.setPreviousAttempts(pending.getAttempts()); } else { pending.setPreviousHash(""); - pending.setPreviousExpiresAt(Instant.EPOCH); + pending.setPreviousExpiresAt(0L); pending.setPreviousAttempts(0); } pending.setCodeHash(codeHash); - pending.setExpiresAt(Instant.ofEpochMilli(now + CODE_SECONDS * 1000L)); + pending.setExpiresAt(now + CODE_SECONDS * 1000L); pending.setAttempts(0); - pending.setSentAt(Instant.ofEpochMilli(now)); + pending.setSentAt(now); if (first) { codes.insert(pending); } @@ -149,7 +148,7 @@ void discard(String username, String codeHash) throws IOException { return; } if (pending.getPreviousHash().length() == 0 - || pending.getPreviousExpiresAt().isBefore(Instant.now())) { + || pending.getPreviousExpiresAt() < System.currentTimeMillis()) { codes.deleteById(username); return; } @@ -157,9 +156,9 @@ void discard(String username, String codeHash) throws IOException { pending.setExpiresAt(pending.getPreviousExpiresAt()); pending.setAttempts(pending.getPreviousAttempts()); pending.setPreviousHash(""); - pending.setPreviousExpiresAt(Instant.EPOCH); + pending.setPreviousExpiresAt(0L); pending.setPreviousAttempts(0); - pending.setSentAt(Instant.EPOCH); + pending.setSentAt(0L); } /// Checks the code the user typed. Answers 400 for a wrong or expired one @@ -187,7 +186,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().isBefore(Instant.now())) { + if (pending == null || pending.getExpiresAt() < System.currentTimeMillis()) { throw new ResponseStatusException(400, "That code has expired. Ask for a new one"); } if (pending.getAttempts() >= MAX_ATTEMPTS) { @@ -223,7 +222,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().isBefore(Instant.now()) + && pending.getPreviousExpiresAt() >= System.currentTimeMillis() && 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 124da6a1ff0..5e476f363bf 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,7 +48,6 @@ 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; @@ -124,8 +123,8 @@ public AdminStatsDto dashboard() throws IOException { } } int online = (int) cars.countByOnlineTrueAndLastSeenGreaterThanEqual( - Instant.ofEpochMilli(now - Matcher.FRESH_MILLIS)); - int today = (int) orders.countByPlacedAtGreaterThanEqual(Instant.ofEpochMilli(Days.start(now))); + now - Matcher.FRESH_MILLIS); + int today = (int) orders.countByPlacedAtGreaterThanEqual(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)); @@ -154,10 +153,10 @@ public StatsSeriesDto series(int days) throws IOException { long finished = 0L; long totalSum = 0L; long tookMillis = 0L; - List timeline = orders.timeline(Instant.ofEpochMilli(since)); + List timeline = orders.timeline(since); for (int iter = 0; iter < timeline.size(); iter++) { Object[] order = timeline.get(iter); - long at = Rows.millis(order[1]); + long at = whole(order[1]); OrderState state = Rows.orderState(order[2]); byHour[(int) (at % Days.MILLIS / 3600000L)]++; if (state != null) { @@ -169,7 +168,7 @@ public StatsSeriesDto series(int days) throws IOException { delivered++; finished++; totalSum += whole(order[3]); - tookMillis += Math.max(0L, Rows.millis(order[5]) - at); + tookMillis += Math.max(0L, whole(order[5]) - at); } else if (ended(state)) { finished++; } @@ -187,7 +186,7 @@ public StatsSeriesDto series(int days) throws IOException { } } Map completedBy = new HashMap(); - List perCourier = deliveries.countByCourier(Instant.ofEpochMilli(since), DeliveryState.COMPLETED); + List perCourier = deliveries.countByCourier(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])}); @@ -204,7 +203,7 @@ public StatsSeriesDto series(int days) throws IOException { } } List byRestaurant = new ArrayList(); - List kitchens = orders.countByRestaurant(Instant.ofEpochMilli(since)); + List kitchens = orders.countByRestaurant(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. @@ -221,9 +220,9 @@ public StatsSeriesDto series(int days) throws IOException { double completionRate = finished == 0L ? 0d : Math.round(delivered * 100d / finished) / 100d; - List signUps = profiles.signUps(Instant.ofEpochMilli(since)); + List signUps = profiles.signUps(since); for (int iter = 0; iter < signUps.size(); iter++) { - int index = (int) ((signUps.get(iter).toEpochMilli() - since) / Days.MILLIS); + int index = (int) ((signUps.get(iter).longValue() - 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 0e126aa1b5f..0e61b522f0d 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,7 +45,6 @@ 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; @@ -344,7 +343,7 @@ public RestaurantSummaryDto favorite(String viewer, String id, boolean keep) Favorite row = new Favorite(); row.setUsername(viewer); row.setRestaurantId(id); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); 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 2a23086e5ae..0fadb79eb42 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,7 +42,6 @@ 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 @@ -267,8 +266,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(Instant.ofEpochMilli(now - (60 - iter) * 86400000L)); - restaurant.setUpdatedAt(Instant.ofEpochMilli(now)); + restaurant.setCreatedAt(now - (60 - iter) * 86400000L); + restaurant.setUpdatedAt(now); restaurants.insert(restaurant); menu(restaurant.getId(), MENUS[iter]); } @@ -292,8 +291,8 @@ public void seed(String merchant) throws IOException { waiting.setPhotoId(""); waiting.setApplicant(""); waiting.setReason(""); - waiting.setCreatedAt(Instant.ofEpochMilli(now - 2L * 86400000L)); - waiting.setUpdatedAt(Instant.ofEpochMilli(now - 2L * 86400000L)); + waiting.setCreatedAt(now - 2L * 86400000L); + waiting.setUpdatedAt(now - 2L * 86400000L); restaurants.insert(waiting); promo("WELCOME10", 10, 0L, 1500L, now); @@ -372,7 +371,7 @@ private String photo(String key, String restaurantId) throws IOException { row.setRestaurantId(restaurantId); row.setContentType(type); row.setData(read(file)); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); photos.insert(row); return id; } @@ -396,7 +395,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(Instant.ofEpochMilli(now)); + promo.setCreatedAt(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 f90eecb347e..869bc359a6d 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,7 +56,6 @@ 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; @@ -151,8 +150,8 @@ public RestaurantDto apply(String username, RestaurantEditDto form) throws IOExc restaurant.setReason(""); restaurant.setPhotoId(""); long now = System.currentTimeMillis(); - restaurant.setCreatedAt(Instant.ofEpochMilli(now)); - restaurant.setUpdatedAt(Instant.ofEpochMilli(now)); + restaurant.setCreatedAt(now); + restaurant.setUpdatedAt(now); fill(restaurant, form); restaurants.insert(restaurant); return catalog.detail(restaurant, username, 0d, 0d, true); @@ -183,7 +182,7 @@ public PhotoDto applicationPhoto(String username, PhotoDto photo) throws IOExcep } PhotoDto saved = store(last.getId(), photo); last.setPhotoId(saved.id()); - last.setUpdatedAt(Instant.now()); + last.setUpdatedAt(System.currentTimeMillis()); return saved; } @@ -259,7 +258,7 @@ public RestaurantDto approve(String by, String id) throws IOException { } restaurant.setStatus(Catalog.APPROVED); restaurant.setReason(""); - restaurant.setUpdatedAt(Instant.now()); + restaurant.setUpdatedAt(System.currentTimeMillis()); if (!staff.existsById(Identifier.of(restaurant.getId(), applicant))) { RestaurantStaff row = new RestaurantStaff(); row.setRestaurantId(restaurant.getId()); @@ -282,7 +281,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(Instant.now()); + restaurant.setUpdatedAt(System.currentTimeMillis()); return catalog.detail(restaurant, null, 0d, 0d, true); } @@ -307,7 +306,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(Instant.now()); + restaurant.setUpdatedAt(System.currentTimeMillis()); return catalog.detail(restaurant, null, 0d, 0d, true); } @@ -351,7 +350,7 @@ public RestaurantDto save(String username, RestaurantEditDto form) throws IOExce ownPhoto(restaurant, form.photoId()); restaurant.setPhotoId(form.photoId()); } - restaurant.setUpdatedAt(Instant.now()); + restaurant.setUpdatedAt(System.currentTimeMillis()); return catalog.detail(restaurant, username, 0d, 0d, true); } @@ -360,7 +359,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(Instant.now()); + restaurant.setUpdatedAt(System.currentTimeMillis()); return catalog.detail(restaurant, username, 0d, 0d, true); } @@ -373,7 +372,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, Instant.ofEpochMilli(week)); + restaurant.getId(), OrderState.DELIVERED, week); long count = 0L; long todayCents = 0L; long weekCents = 0L; @@ -387,7 +386,7 @@ public MerchantSummaryDto summary(String username) throws IOException { long earned = order.getSubtotalCents() - order.getDiscountCents() - order.getCommissionCents(); weekCents += earned; - if (order.getDeliveredAt().toEpochMilli() >= today) { + if (order.getDeliveredAt() >= today) { todayCents += earned; count++; } @@ -607,7 +606,7 @@ private PhotoDto store(String restaurantId, PhotoDto photo) throws IOException { row.setRestaurantId(restaurantId); row.setContentType(type); row.setData(bytes); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); photos.insert(row); return new PhotoDto(row.getId(), type, ""); } @@ -625,14 +624,14 @@ private int prune(String restaurantId) { for (int iter = 0; iter < menu.size(); iter++) { used.add(menu.get(iter).getPhotoId()); } - Instant before = Instant.now().minusMillis(UNUSED_PHOTO_GRACE); + long before = System.currentTimeMillis() - 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]; - boolean aged = at instanceof Instant && ((Instant) at).isBefore(before); - if (id instanceof String && !used.contains(id) && aged) { + long createdAt = at instanceof Number ? ((Number) at).longValue() : Long.MAX_VALUE; + if (id instanceof String && !used.contains(id) && createdAt < before) { 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 484fd01d5fb..f1c1253ab0a 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,7 +47,6 @@ 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; @@ -157,14 +156,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().toEpochMilli() : 0L; + long since = state != null && state.isOnline() ? now - state.getLastSeen() : 0L; boolean first = state == null; if (first) { state = new CourierState(); state.setUsername(courier); } state.setOnline(status.online()); - state.setLastSeen(Instant.ofEpochMilli(now)); + state.setLastSeen(now); // Off line keeps the last position: there is none to report. A first // report stores whatever came with it. if (status.online() || first) { @@ -283,10 +282,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, Instant.ofEpochMilli(now - now % DAY_MILLIS)); + Object[] day = deliveries.paidTotalsSince(courier, 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, Instant.ofEpochMilli(now - 7 * DAY_MILLIS))); + long week = Rows.number(deliveries.paidSince(courier, 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]); @@ -306,7 +305,7 @@ private static CourierDto toDto(Profile profile, CourierApplication application, double rating = 5d; long lastSeen = 0L; if (car != null) { - lastSeen = car.getLastSeen().toEpochMilli(); + lastSeen = car.getLastSeen(); // 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 a345522114d..d082b078f0c 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,7 +48,6 @@ 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; @@ -116,16 +115,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, Instant.ofEpochMilli(monthStart)); + DeliveryState.COMPLETED, 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, Instant.ofEpochMilli(monthStart))); + deliveries.tipChargedSince(courier, monthStart)); for (int iter = 0; iter < done.size(); iter++) { Delivery delivery = done.get(iter); - long at = delivery.getUpdatedAt().toEpochMilli(); + long at = delivery.getUpdatedAt(); 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 @@ -198,7 +197,7 @@ public PayoutDto cashOut(String courier) throws IOException { row.setCourier(courier); row.setAmountCents(amount); row.setStatus("paid"); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); row.setDestination(account.getBankName() + " ****" + account.getLast4()); payouts.insert(row); return toDto(row); @@ -298,6 +297,6 @@ private static PayoutAccountDto toDto(PayoutAccount row) { private static PayoutDto toDto(Payout row) { return new PayoutDto(row.getId(), row.getAmountCents(), row.getStatus(), - row.getCreatedAt().toEpochMilli(), row.getDestination()); + row.getCreatedAt(), 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 8c5bab31928..0e556c6e391 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,7 +56,6 @@ 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; @@ -178,9 +177,9 @@ public void dispatch(CustomerOrder order, Restaurant restaurant) throws IOExcept delivery.setMethodLabel(order.getMethodLabel()); delivery.setPaymentStatus(order.getPaymentStatus()); delivery.setNote(order.getNote()); - delivery.setRequestedAt(Instant.ofEpochMilli(now)); - delivery.setUpdatedAt(Instant.ofEpochMilli(now)); - delivery.setSearchUntil(Instant.ofEpochMilli(now + searchMillis)); + delivery.setRequestedAt(now); + delivery.setUpdatedAt(now); + delivery.setSearchUntil(now + searchMillis); deliveries.insert(delivery); event(order.getId(), DeliveryState.REQUESTED, ""); } @@ -280,7 +279,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, Instant.now()) == 1) { + OrderState.DELIVERED, System.currentTimeMillis()) == 1) { orderEvents.record(id, OrderState.DELIVERED, courier); } return delivery; @@ -335,13 +334,13 @@ public void settleLeftBehind() throws IOException { @Transactional(readOnly = true) private List unsettled(long after, long before) { - return deliveries.unsettled(Instant.ofEpochMilli(after), Instant.ofEpochMilli(before), new PageRequest(0, 50)); + return deliveries.unsettled(after, 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, Instant.now()); + orders.paymentStatus(id, status, System.currentTimeMillis()); Delivery delivery = find(id); return new Change(id, delivery.getState(), delivery.getCustomer(), delivery.getCourier(), "", toDto(delivery, courier, new HashMap())); @@ -360,7 +359,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, - Instant.now(), courier, "") != 1) { + System.currentTimeMillis(), courier, "") != 1) { throw new ResponseStatusException(409, "That delivery is " + describe(find(id).getState())); } @@ -395,7 +394,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, Instant.now()) != 1) { + OrderState.PICKED_UP, System.currentTimeMillis()) != 1) { throw new ResponseStatusException(409, "The kitchen has not marked it ready yet"); } orderEvents.record(id, OrderState.PICKED_UP, courier); @@ -495,17 +494,17 @@ private Change choose(String id, String[] chosen) throws IOException { return null; } long now = System.currentTimeMillis(); - if (now > delivery.getSearchUntil().toEpochMilli()) { + if (now > delivery.getSearchUntil()) { 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", Instant.ofEpochMilli(now)) == 1) { + OrderState.NO_COURIERS, "No courier was free to bring it", 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().toEpochMilli()); + chosen[0] = matcher.pick(delivery, now - delivery.getRequestedAt()); return null; } @@ -536,7 +535,7 @@ Change offer(String id, String courier) throws IOException { return null; } long now = System.currentTimeMillis(); - if (!matcher.fits(delivery, courier, now - delivery.getRequestedAt().toEpochMilli())) { + if (!matcher.fits(delivery, courier, now - delivery.getRequestedAt())) { return null; } return tryMove(id, DeliveryState.OFFERED, "", null, courier, Long.valueOf(now + offerMillis)) @@ -585,7 +584,7 @@ public void tick() throws IOException { @Transactional(readOnly = true) private List lapsedOffers(long now) throws IOException { - return deliveries.findByStateAndOfferExpiresAtLessThan(DeliveryState.OFFERED, Instant.ofEpochMilli(now)); + return deliveries.findByStateAndOfferExpiresAtLessThan(DeliveryState.OFFERED, now); } @Transactional(readOnly = true) @@ -724,11 +723,10 @@ private boolean tryMove(String id, DeliveryState to, String actor, String ownerF if (sources.length == 0) { return false; } - Instant now = Instant.now(); + long now = System.currentTimeMillis(); int moved; if (newOfferExpiresAt != null) { - moved = deliveries.offer(id, sources, to, now, newCourier, - Instant.ofEpochMilli(newOfferExpiresAt.longValue())); + moved = deliveries.offer(id, sources, to, now, newCourier, newOfferExpiresAt.longValue()); } else if (CUSTOMER.equals(ownerField)) { moved = deliveries.moveAsCustomer(id, sources, to, now, actor); } else if (!COURIER.equals(ownerField)) { @@ -756,7 +754,7 @@ private void event(String id, DeliveryState state, String actor) throws IOExcept event.setDeliveryId(id); event.setState(state); event.setActor(actor); - event.setCreatedAt(Instant.now()); + event.setCreatedAt(System.currentTimeMillis()); events.insert(event); } @@ -890,7 +888,7 @@ private DeliveryDto toDto(Delivery delivery, String viewer, Map } if (offered) { offerExpiresInSeconds = (int) Math.max(0L, - (delivery.getOfferExpiresAt().toEpochMilli() - System.currentTimeMillis()) / 1000L); + (delivery.getOfferExpiresAt() - System.currentTimeMillis()) / 1000L); } long fareCents = delivery.getFareCents(); long tip = delivery.getTipCents(); @@ -923,8 +921,8 @@ private DeliveryDto toDto(Delivery delivery, String viewer, Map delivery.getCurrency(), delivery.getDistanceMeters(), delivery.getDurationSeconds(), - delivery.getRequestedAt().toEpochMilli(), - delivery.getUpdatedAt().toEpochMilli(), + delivery.getRequestedAt(), + delivery.getUpdatedAt(), 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 226f645a0e8..3d632f9b9a7 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,7 +37,6 @@ 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; @@ -133,7 +132,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(Instant.now().minusMillis(FRESH_MILLIS), + List boxed = couriers.freeInBox(System.currentTimeMillis() - 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 07f19a9c45c..14f1392da29 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,7 +21,6 @@ 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. @@ -32,7 +31,7 @@ public class ClosedAccount { private String usernameHash = ""; @Column(nullable = false) - private Instant closedAt = Instant.EPOCH; + private long closedAt; public ClosedAccount() { } @@ -45,11 +44,11 @@ public void setUsernameHash(String usernameHash) { this.usernameHash = usernameHash; } - public Instant getClosedAt() { + public long getClosedAt() { return closedAt; } - public void setClosedAt(Instant closedAt) { + public void setClosedAt(long 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 1c5662f6f58..dabb9e342e9 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,7 +21,6 @@ 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 @@ -64,13 +63,13 @@ public class CourierApplication { private String rejectionReason = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) - private Instant submittedAt = Instant.EPOCH; + private long submittedAt; @Column(nullable = false) - private Instant reviewedAt = Instant.EPOCH; + private long reviewedAt; @Column(nullable = false, type = "VARCHAR(190)") private String reviewedBy = ""; @@ -174,27 +173,27 @@ public void setRejectionReason(String rejectionReason) { this.rejectionReason = rejectionReason; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } - public Instant getSubmittedAt() { + public long getSubmittedAt() { return submittedAt; } - public void setSubmittedAt(Instant submittedAt) { + public void setSubmittedAt(long submittedAt) { this.submittedAt = submittedAt; } - public Instant getReviewedAt() { + public long getReviewedAt() { return reviewedAt; } - public void setReviewedAt(Instant reviewedAt) { + public void setReviewedAt(long 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 cb5f0d610d7..51f6214e105 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,7 +21,6 @@ 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. @@ -42,7 +41,7 @@ public class CourierDocument { private String status = ""; @Column(nullable = false) - private Instant uploadedAt = Instant.EPOCH; + private long uploadedAt; @Column(nullable = false) private String data = ""; @@ -82,11 +81,11 @@ public void setStatus(String status) { this.status = status; } - public Instant getUploadedAt() { + public long getUploadedAt() { return uploadedAt; } - public void setUploadedAt(Instant uploadedAt) { + public void setUploadedAt(long 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 6401313002d..85d1049a05c 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,7 +21,6 @@ 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 @@ -43,7 +42,7 @@ public class CourierState { private double heading; @Column(nullable = false) - private Instant lastSeen = Instant.EPOCH; + private long lastSeen; @Column(nullable = false) private long ratingSum; @@ -99,11 +98,11 @@ public void setHeading(double heading) { this.heading = heading; } - public Instant getLastSeen() { + public long getLastSeen() { return lastSeen; } - public void setLastSeen(Instant lastSeen) { + public void setLastSeen(long 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 b1f2b1494c9..d34529b2739 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,7 +23,6 @@ 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 @@ -108,19 +107,19 @@ public class CustomerOrder { private int prepMinutes; @Column(nullable = false) - private Instant placedAt = Instant.EPOCH; + private long placedAt; @Column(nullable = false) - private Instant acceptedAt = Instant.EPOCH; + private long acceptedAt; @Column(nullable = false) - private Instant readyAt = Instant.EPOCH; + private long readyAt; @Column(nullable = false) - private Instant deliveredAt = Instant.EPOCH; + private long deliveredAt; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; @Column(nullable = false, type = "VARCHAR(255)") private String reason = ""; @@ -331,43 +330,43 @@ public void setPrepMinutes(int prepMinutes) { this.prepMinutes = prepMinutes; } - public Instant getPlacedAt() { + public long getPlacedAt() { return placedAt; } - public void setPlacedAt(Instant placedAt) { + public void setPlacedAt(long placedAt) { this.placedAt = placedAt; } - public Instant getAcceptedAt() { + public long getAcceptedAt() { return acceptedAt; } - public void setAcceptedAt(Instant acceptedAt) { + public void setAcceptedAt(long acceptedAt) { this.acceptedAt = acceptedAt; } - public Instant getReadyAt() { + public long getReadyAt() { return readyAt; } - public void setReadyAt(Instant readyAt) { + public void setReadyAt(long readyAt) { this.readyAt = readyAt; } - public Instant getDeliveredAt() { + public long getDeliveredAt() { return deliveredAt; } - public void setDeliveredAt(Instant deliveredAt) { + public void setDeliveredAt(long deliveredAt) { this.deliveredAt = deliveredAt; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 64075d9c942..174d2eb5ea3 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,7 +22,6 @@ 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. @@ -76,16 +75,16 @@ public class Delivery { private double durationSeconds; @Column(nullable = false) - private Instant requestedAt = Instant.EPOCH; + private long requestedAt; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; @Column(nullable = false) - private Instant offerExpiresAt = Instant.EPOCH; + private long offerExpiresAt; @Column(nullable = false) - private Instant searchUntil = Instant.EPOCH; + private long searchUntil; @Column(nullable = false, type = "SMALLINT") private int stars; @@ -226,35 +225,35 @@ public void setDurationSeconds(double durationSeconds) { this.durationSeconds = durationSeconds; } - public Instant getRequestedAt() { + public long getRequestedAt() { return requestedAt; } - public void setRequestedAt(Instant requestedAt) { + public void setRequestedAt(long requestedAt) { this.requestedAt = requestedAt; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long updatedAt) { this.updatedAt = updatedAt; } - public Instant getOfferExpiresAt() { + public long getOfferExpiresAt() { return offerExpiresAt; } - public void setOfferExpiresAt(Instant offerExpiresAt) { + public void setOfferExpiresAt(long offerExpiresAt) { this.offerExpiresAt = offerExpiresAt; } - public Instant getSearchUntil() { + public long getSearchUntil() { return searchUntil; } - public void setSearchUntil(Instant searchUntil) { + public void setSearchUntil(long 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 1e8b9d4eebf..b44ee60cffa 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,7 +21,6 @@ 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 @@ -39,12 +38,12 @@ public class DeliveryActivity { /// When the server last sent it a state, for spacing out the updates. @Column(nullable = false) - private Instant sentAt = Instant.EPOCH; + private long sentAt; /// 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 Instant endedAt = Instant.EPOCH; + private long endedAt; public DeliveryActivity() { } @@ -73,19 +72,19 @@ public void setActivityId(String activityId) { this.activityId = activityId; } - public Instant getSentAt() { + public long getSentAt() { return sentAt; } - public void setSentAt(Instant sentAt) { + public void setSentAt(long sentAt) { this.sentAt = sentAt; } - public Instant getEndedAt() { + public long getEndedAt() { return endedAt; } - public void setEndedAt(Instant endedAt) { + public void setEndedAt(long 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 1ac81efdafb..53e646b615c 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,7 +22,6 @@ 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 @@ -41,7 +40,7 @@ public class DeliveryEvent { private String actor = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public DeliveryEvent() { } @@ -78,11 +77,11 @@ public void setActor(String actor) { this.actor = actor; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 6161bf14cfd..0c6e5d11b64 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,7 +21,6 @@ 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 @@ -35,7 +34,7 @@ public class Favorite { private String restaurantId = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public Favorite() { } @@ -56,11 +55,11 @@ public void setRestaurantId(String restaurantId) { this.restaurantId = restaurantId; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 801de0c7994..4e0f5fecd38 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,7 +21,6 @@ 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 @@ -34,7 +33,7 @@ public class LiveTicket { private String username = ""; @Column(nullable = false) - private Instant expiresAt = Instant.EPOCH; + private long expiresAt; public LiveTicket() { } @@ -55,11 +54,11 @@ public void setUsername(String username) { this.username = username; } - public Instant getExpiresAt() { + public long getExpiresAt() { return expiresAt; } - public void setExpiresAt(Instant expiresAt) { + public void setExpiresAt(long 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 d8c37f92589..0ad8aeb3fdb 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,7 +21,6 @@ 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 @@ -34,7 +33,7 @@ public class ModerationEvent { private String username = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(190)") private String actor = ""; @@ -64,11 +63,11 @@ public void setUsername(String username) { this.username = username; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 a9a98afadd0..94d091face4 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,7 +23,6 @@ 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 @@ -42,7 +41,7 @@ public class OrderEvent { private String actor = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public OrderEvent() { } @@ -79,11 +78,11 @@ public void setActor(String actor) { this.actor = actor; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 5c4cc53be74..8157760cf44 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,7 +21,6 @@ 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 @@ -43,7 +42,7 @@ public class Payment { private String providerRef = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(64)") private String tipRef = ""; @@ -58,7 +57,7 @@ public class Payment { private String refundReason = ""; @Column(nullable = false) - private Instant refundedAt = Instant.EPOCH; + private long refundedAt; public Payment() { } @@ -103,11 +102,11 @@ public void setProviderRef(String providerRef) { this.providerRef = providerRef; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } @@ -143,11 +142,11 @@ public void setRefundReason(String refundReason) { this.refundReason = refundReason; } - public Instant getRefundedAt() { + public long getRefundedAt() { return refundedAt; } - public void setRefundedAt(Instant refundedAt) { + public void setRefundedAt(long 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 4edbb85fabc..8edddcfdf35 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,7 +21,6 @@ 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. @@ -53,7 +52,7 @@ public class PaymentMethod { private boolean preferred; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public PaymentMethod() { } @@ -122,11 +121,11 @@ public void setPreferred(boolean preferred) { this.preferred = preferred; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 5b0757fee9c..410658a37e0 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,7 +21,6 @@ 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 @@ -37,7 +36,7 @@ public class PaymentSetup { private String reference = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) private boolean completed; @@ -69,11 +68,11 @@ public void setReference(String reference) { this.reference = reference; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 69c99a0ff6b..295beb14887 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,7 +21,6 @@ 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 @@ -40,7 +39,7 @@ public class Payout { private String status = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(120)") private String destination = ""; @@ -80,11 +79,11 @@ public void setStatus(String status) { this.status = status; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 db6ea1e2477..87115e9f825 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,7 +21,6 @@ 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 @@ -34,20 +33,20 @@ public class PhoneCode { private String codeHash = ""; @Column(nullable = false) - private Instant expiresAt = Instant.EPOCH; + private long expiresAt; @Column(nullable = false) private int attempts; @Column(nullable = false) - private Instant sentAt = Instant.EPOCH; + private long sentAt; /// 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 Instant previousExpiresAt = Instant.EPOCH; + private long previousExpiresAt; /// 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. @@ -73,11 +72,11 @@ public void setCodeHash(String codeHash) { this.codeHash = codeHash; } - public Instant getExpiresAt() { + public long getExpiresAt() { return expiresAt; } - public void setExpiresAt(Instant expiresAt) { + public void setExpiresAt(long expiresAt) { this.expiresAt = expiresAt; } @@ -89,11 +88,11 @@ public void setAttempts(int attempts) { this.attempts = attempts; } - public Instant getSentAt() { + public long getSentAt() { return sentAt; } - public void setSentAt(Instant sentAt) { + public void setSentAt(long sentAt) { this.sentAt = sentAt; } @@ -105,11 +104,11 @@ public void setPreviousHash(String previousHash) { this.previousHash = previousHash; } - public Instant getPreviousExpiresAt() { + public long getPreviousExpiresAt() { return previousExpiresAt; } - public void setPreviousExpiresAt(Instant previousExpiresAt) { + public void setPreviousExpiresAt(long 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 b26494ea2ca..10c7a383d9a 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,7 +21,6 @@ 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 @@ -37,7 +36,7 @@ public class Photo { private String contentType = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) private byte[] data = new byte[0]; @@ -69,11 +68,11 @@ public void setContentType(String contentType) { this.contentType = contentType; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 ab0cea02412..5fe90ebfb8e 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,7 +21,6 @@ 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. @@ -56,7 +55,7 @@ public class Pricing { private double commissionPercent; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; @Column(nullable = false, type = "VARCHAR(190)") private String updatedBy = ""; @@ -136,11 +135,11 @@ public void setCommissionPercent(double commissionPercent) { this.commissionPercent = commissionPercent; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 d4c63522b49..d9bdfef5872 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,7 +21,6 @@ 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. /// @@ -49,7 +48,7 @@ public class Profile { private String plate = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(8)") private String language = "en"; @@ -111,11 +110,11 @@ public void setPlate(String plate) { this.plate = plate; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 0d07ce19894..384b8cf25d7 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,7 +21,6 @@ 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. @@ -44,7 +43,7 @@ public class Promo { private boolean active; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public Promo() { } @@ -89,11 +88,11 @@ public void setActive(boolean active) { this.active = active; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 ec59e720d4a..d5c941dde26 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,7 +21,6 @@ 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. /// @@ -47,7 +46,7 @@ public class PushDevice { private String platform = ""; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; public PushDevice() { } @@ -92,11 +91,11 @@ public void setPlatform(String platform) { this.platform = platform; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 23b931465eb..cd0cf9878ba 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,7 +21,6 @@ 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. @@ -86,10 +85,10 @@ public class Restaurant { private String reason = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; public Restaurant() { } @@ -246,19 +245,19 @@ public void setReason(String reason) { this.reason = reason; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 43a6b2f66fa..2065edf1f35 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,7 +21,6 @@ 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 @@ -49,7 +48,7 @@ public class SavedAddress { private String note = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public SavedAddress() { } @@ -110,11 +109,11 @@ public void setNote(String note) { this.note = note; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 c4e4d3a167f..8cf7d0215b7 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,7 +28,6 @@ import com.codenameone.examples.savor.repository.LiveTicketRepository; import java.io.IOException; -import java.time.Instant; /// Tickets for the live channel. /// @@ -59,7 +58,7 @@ public TicketDto issue(String username) throws IOException { LiveTicket row = new LiveTicket(); row.setTicketHash(Ids.sha256(ticket)); row.setUsername(username); - row.setExpiresAt(Instant.ofEpochMilli(System.currentTimeMillis() + TICKET_SECONDS * 1000L)); + row.setExpiresAt(System.currentTimeMillis() + TICKET_SECONDS * 1000L); tickets.insert(row); return new TicketDto(ticket, TICKET_SECONDS); } @@ -79,7 +78,7 @@ public String redeem(String ticket) throws IOException { return null; } String username = row.getUsername(); - long expiresAt = row.getExpiresAt().toEpochMilli(); + long 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); @@ -93,7 +92,7 @@ public String redeem(String ticket) throws IOException { @Scheduled(fixedDelay = 60000, initialDelay = 60000) @Transactional public void sweep() throws IOException { - tickets.deleteByExpiresAtLessThan(Instant.now()); + tickets.deleteByExpiresAtLessThan(System.currentTimeMillis()); } /// 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 ce62acc5b13..64e1c6652ac 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,7 +30,6 @@ 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; @@ -45,7 +44,6 @@ 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; @@ -246,13 +244,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", Instant.ofEpochMilli(now), data) == 0) { + if (documents.replace(username, kind, type, "uploaded", now, data) == 0) { CourierDocument document = new CourierDocument(); document.setUsername(username); document.setKind(kind); document.setContentType(type); document.setStatus("uploaded"); - document.setUploadedAt(Instant.ofEpochMilli(now)); + document.setUploadedAt(now); document.setData(data); documents.insert(document); } @@ -312,7 +310,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, Instant.now()); + applications.submit(username, was, PENDING, System.currentTimeMillis()); return get(username); } @@ -426,7 +424,7 @@ public void grant(String by, String username) throws IOException { applications.insert(blank(username, APPROVED, "", "")); return; } - applications.approveUnlessApproved(username, APPROVED, Instant.now(), by); + applications.approveUnlessApproved(username, APPROVED, System.currentTimeMillis(), by); } /// Takes the approval back, when an admin withdraws the COURIER role. The @@ -434,7 +432,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", - Instant.now(), by); + System.currentTimeMillis(), by); } /// Everything kept about an account's application, for an account being @@ -455,7 +453,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, Instant.now(), by) + if (applications.move(username, PENDING, to, reason, System.currentTimeMillis(), by) != 1) { throw new ResponseStatusException(409, "That application is not waiting for an answer"); } @@ -536,8 +534,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(Instant.ofEpochMilli(now)); - application.setReviewedAt(APPROVED.equals(status) ? Instant.ofEpochMilli(now) : Instant.EPOCH); + application.setCreatedAt(now); + application.setReviewedAt(APPROVED.equals(status) ? now : 0L); return application; } @@ -568,7 +566,8 @@ private static CourierApplicationDto toDto(String username, String name, Object[] stored = documents.get(iter); if (KINDS[kind].equals(stored[from])) { status = (String) stored[from + 1]; - uploadedAt = Rows.millis(stored[from + 2]); + Object at = stored[from + 2]; + uploadedAt = at instanceof Number ? ((Number) at).longValue() : 0L; } } listed.add(new DocumentDto(KINDS[kind], status, uploadedAt)); @@ -582,7 +581,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().toEpochMilli(), row.getReviewedAt().toEpochMilli(), + row.getRejectionReason(), row.getSubmittedAt(), row.getReviewedAt(), 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 eecfc124c9b..48261e9e938 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,7 +29,6 @@ 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; @@ -78,7 +77,7 @@ public SavedAddressDto save(String username, SavedAddressDto form) throws IOExce row = new SavedAddress(); row.setId(Ids.next()); row.setUsername(username); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); } 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 1d8c20aae98..de13aa5c456 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,7 +28,6 @@ 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: @@ -63,7 +62,7 @@ public void cook() throws IOException { return; } long now = System.currentTimeMillis(); - List waiting = unattended(OrderState.PLACED, Instant.ofEpochMilli(now - ACCEPT_AFTER_MILLIS)); + List waiting = unattended(OrderState.PLACED, now - ACCEPT_AFTER_MILLIS); for (int iter = 0; iter < waiting.size(); iter++) { CustomerOrder order = waiting.get(iter); try { @@ -73,7 +72,7 @@ public void cook() throws IOException { // Cancelled or turned down in the meantime. } } - List cooking = unattended(OrderState.ACCEPTED, Instant.ofEpochMilli(now - READY_AFTER_MILLIS)); + List cooking = unattended(OrderState.ACCEPTED, now - READY_AFTER_MILLIS); for (int iter = 0; iter < cooking.size(); iter++) { CustomerOrder order = cooking.get(iter); try { @@ -86,7 +85,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, Instant before) { + private List unattended(OrderState state, long 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 88392e3bbc0..82a3b972b2f 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,7 +49,6 @@ 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; @@ -227,12 +226,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(Instant.ofEpochMilli(at)); - order.setUpdatedAt(Instant.ofEpochMilli(ended)); + order.setPlacedAt(at); + order.setUpdatedAt(ended); order.setAcceptedAt(OrderState.REJECTED == state - || 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); + || OrderState.CANCELLED_BY_CUSTOMER == state ? 0L : accepted); + order.setReadyAt(delivered ? ready : 0L); + order.setDeliveredAt(delivered ? ended : 0L); 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" @@ -271,9 +270,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(Instant.ofEpochMilli(accepted)); - delivery.setUpdatedAt(Instant.ofEpochMilli(ended)); - delivery.setSearchUntil(Instant.ofEpochMilli(accepted + 900000L)); + delivery.setRequestedAt(accepted); + delivery.setUpdatedAt(ended); + delivery.setSearchUntil(accepted + 900000L); delivery.setStars(given); delivery.setPaymentStatus(delivered ? Payments.PAID : Payments.PENDING); delivery.setMethodId(method[0]); @@ -301,7 +300,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(Instant.ofEpochMilli(ended)); + payment.setCreatedAt(ended); paid.insert(payment); lastSeen[courierIndex] = Math.max(lastSeen[courierIndex], ended); if (ended < now - 7L * Days.MILLIS) { @@ -325,7 +324,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(Instant.ofEpochMilli(lastSeen[iter])); + state.setLastSeen(lastSeen[iter]); state.setRatingSum(stars[iter]); state.setRatingCount(rated[iter]); if (first) { @@ -344,7 +343,7 @@ public void seed(String[] customers, String[] couriers) throws IOException { payout.setCourier(couriers[iter]); payout.setAmountCents(earnedEarlier[iter]); payout.setStatus("paid"); - payout.setCreatedAt(Instant.ofEpochMilli(now - 7L * Days.MILLIS)); + payout.setCreatedAt(now - 7L * Days.MILLIS); payout.setDestination("Bay Credit Union ****67" + (10 + iter)); payouts.insert(payout); } @@ -358,7 +357,7 @@ private void orderEvent(String order, OrderState state, String actor, long at) event.setOrderId(order); event.setState(state); event.setActor(actor); - event.setCreatedAt(Instant.ofEpochMilli(at)); + event.setCreatedAt(at); orderEvents.insert(event); } @@ -369,7 +368,7 @@ private void deliveryEvent(String delivery, DeliveryState state, String actor, l event.setDeliveryId(delivery); event.setState(state); event.setActor(actor); - event.setCreatedAt(Instant.ofEpochMilli(at)); + event.setCreatedAt(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 2bdd7ff8f11..b9388a118e3 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,7 +24,6 @@ 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. @@ -42,7 +41,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(Instant.now()); + event.setCreatedAt(System.currentTimeMillis()); 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 77088e66460..6d21f69e3dd 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,7 +53,6 @@ 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; @@ -300,8 +299,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(Instant.ofEpochMilli(now)); - order.setUpdatedAt(Instant.ofEpochMilli(now)); + order.setPlacedAt(now); + order.setUpdatedAt(now); order.setReason(""); orders.insert(order); for (int iter = 0; iter < priced.lines.size(); iter++) { @@ -402,7 +401,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, - Instant.now()) != 1) { + System.currentTimeMillis()) != 1) { CustomerOrder now = find(id); throw new ResponseStatusException(409, "That order is " + (now == null ? "gone" : describe(now.getState()))); @@ -427,7 +426,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, Instant.now()) != 1) { + if (orders.rate(id, customer, stars, System.currentTimeMillis()) != 1) { throw new ResponseStatusException(409, "That order is already rated"); } restaurants.addRating(order.getRestaurantId(), stars); @@ -502,7 +501,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, Instant.now()) != 1) { + OrderState.ACCEPTED, prepMinutes, System.currentTimeMillis()) != 1) { throw new ResponseStatusException(409, "That order is " + describe(order.getState())); } @@ -532,7 +531,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, - Instant.now()) != 1) { + System.currentTimeMillis()) != 1) { throw new ResponseStatusException(409, "That order is " + describe(order.getState())); } @@ -545,7 +544,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(Instant.now().minusMillis(answerMillis)); + List late = late(System.currentTimeMillis() - answerMillis); for (int iter = 0; iter < late.size(); iter++) { String id = late.get(iter).getId(); try { @@ -563,7 +562,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(Instant.now().minusMillis(UNRELEASED_MILLIS)); + List held = unreleased(System.currentTimeMillis() - UNRELEASED_MILLIS); for (int iter = 0; iter < held.size(); iter++) { payments.release(held.get(iter).getId()); } @@ -577,12 +576,12 @@ public void sweep() throws IOException { OrderState.CANCELLED_BY_CUSTOMER, OrderState.CANCELLED_BY_ADMIN, OrderState.NO_COURIERS}; @Transactional(readOnly = true) - private List late(Instant before) { + private List late(long before) { return orders.findByStateAndPlacedAtLessThan(OrderState.PLACED, before); } @Transactional(readOnly = true) - private List unreleased(Instant before) { + private List unreleased(long before) { return orders.unreleased(ENDED_SHORT, new String[] {Payments.AUTHORIZED, Payments.PENDING}, before, new PageRequest(0, 50)); @@ -717,8 +716,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().toEpochMilli() == 0L ? order.getPlacedAt().toEpochMilli() - : order.getAcceptedAt().toEpochMilli()) + order.getPrepMinutes() * 60000L; + long cooked = (order.getAcceptedAt() == 0L ? order.getPlacedAt() + : order.getAcceptedAt()) + order.getPrepMinutes() * 60000L; int left = (int) Math.max(0L, (cooked - System.currentTimeMillis()) / 60000L); eta = left + ride; } @@ -735,9 +734,8 @@ 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().toEpochMilli(), - order.getAcceptedAt().toEpochMilli(), order.getReadyAt().toEpochMilli(), - order.getDeliveredAt().toEpochMilli(), eta, + order.getPaymentStatus(), order.getPrepMinutes(), order.getPlacedAt(), + order.getAcceptedAt(), order.getReadyAt(), order.getDeliveredAt(), 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 43ed7cd6b3e..5726384ae6d 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,7 +25,6 @@ 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; @@ -78,7 +77,7 @@ public PromoDto save(PromoDto form) { if (unsaved) { row = new Promo(); row.setCode(code); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); } 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 d1b896bc1fd..fd64514b7eb 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,7 +41,6 @@ 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; @@ -120,7 +119,7 @@ public PricingDto pricing() throws IOException { } private PricingDto toDto(Pricing row) { - if (row == null || Instant.EPOCH.equals(row.getUpdatedAt())) { + if (row == null || row.getUpdatedAt() == 0L) { return defaults; } return new PricingDto(defaults.currency(), row.getBaseCents(), row.getPerKmCents(), @@ -144,7 +143,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(), Instant.now(), by) == 0) { + wanted.commissionPercent(), System.currentTimeMillis(), 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 28479f62f9e..35c5fb933c2 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,7 +48,6 @@ 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; @@ -212,7 +211,7 @@ private String customerForSetup(String username) { /// that are neither finished nor abandoned. private void refuseTooManySetups(String username) { if (setups.countByUsernameAndCompletedFalseAndCreatedAtGreaterThan(username, - Instant.now().minusMillis(SETUP_MILLIS)) >= MAX_OPEN_SETUPS) { + System.currentTimeMillis() - SETUP_MILLIS) >= MAX_OPEN_SETUPS) { throw new ResponseStatusException(429, "Too many cards are being added. Finish one, or try again later"); } @@ -229,7 +228,7 @@ private void refuseTooManySetups(String username) { @Transactional public void sweepSetups() throws IOException { setups.deleteByCompletedTrue(); - setups.deleteByCreatedAtLessThan(Instant.now().minusMillis(2L * SETUP_MILLIS)); + setups.deleteByCreatedAtLessThan(System.currentTimeMillis() - 2L * SETUP_MILLIS); } /// Keeps the reference the processor made for a customer on first use, and @@ -277,7 +276,7 @@ private void keepSetup(String username, String id, String reference) { row.setId(id); row.setUsername(username); row.setReference(reference); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); row.setCompleted(false); setups.insert(row); } @@ -340,7 +339,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().plusMillis(SETUP_MILLIS).isBefore(Instant.now())) { + || setup.getCreatedAt() < System.currentTimeMillis() - SETUP_MILLIS) { throw new ResponseStatusException(404, "No such card setup"); } PaymentCustomer customer = customers.findById(username); @@ -369,9 +368,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. - Instant newest = cards.newestAt(username); - Instant now = Instant.now(); - Instant after = newest == null ? Instant.EPOCH : newest.plusMillis(1L); + Long newest = cards.newestAt(username); + long after = newest == null ? 0L : newest.longValue() + 1L; PaymentMethod row = new PaymentMethod(); row.setId(id); row.setUsername(username); @@ -381,7 +379,7 @@ private PaymentMethodDto keepCard(String username, String setupId, String id, row.setExpYear(card.expYear); row.setToken(card.token); row.setPreferred(first); - row.setCreatedAt(after.isAfter(now) ? after : now); + row.setCreatedAt(Math.max(System.currentTimeMillis(), after)); cards.insert(row); return card(row); } @@ -511,8 +509,8 @@ public void forget(String username) throws IOException { } } - private static Instant retriedSince() { - return Instant.now().minusMillis(RETRY_MILLIS); + private static long retriedSince() { + return System.currentTimeMillis() - RETRY_MILLIS; } // --------------------------------------------------------------- charges @@ -593,7 +591,7 @@ private CustomerOrder order(String id) { @Transactional private void orderPaymentStatus(String id, String status) { - orders.paymentStatus(id, status, Instant.now()); + orders.paymentStatus(id, status, System.currentTimeMillis()); } /// Writes what came of a delivery's payment to the delivery and to its @@ -602,7 +600,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, Instant.now()); + orders.paymentStatus(deliveryId, status, System.currentTimeMillis()); } /// Settles a delivery that has just completed and returns [#PAID], [#FAILED], @@ -677,7 +675,7 @@ private void keepPayment(String deliveryId, long amount, String currency, String row.setCurrency(currency); row.setStatus(status); row.setProviderRef(reference); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); payments.insert(row); } @@ -871,7 +869,7 @@ private List refundsPending() { @Transactional private Delivery endRefund(String deliveryId, String outcome) { if (payments.endRefund(deliveryId, outcome, - REFUNDED.equals(outcome) ? Instant.now() : Instant.EPOCH) != 1) { + REFUNDED.equals(outcome) ? System.currentTimeMillis() : 0L) != 1) { return null; } paymentStatus(deliveryId, outcome); @@ -993,7 +991,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 ? Instant.EPOCH : Instant.now()); + payment.setRefundedAt(pending ? 0L : System.currentTimeMillis()); } /// Records a refund of the fare whose tip could not be refunded: the delivery @@ -1006,7 +1004,7 @@ private void keepPartialRefund(String deliveryId, PaymentProvider.Refund fare, S payment.setRefundRef(cut(fare.reference, 64)); payment.setTipRefundRef(""); payment.setRefundReason(reason); - payment.setRefundedAt(Instant.EPOCH); + payment.setRefundedAt(0L); } // -------------------------------------------------------------- receipts @@ -1043,7 +1041,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().toEpochMilli(), admin, + return receipt(delivery, payment == null ? 0L : payment.getCreatedAt(), admin, new HashMap()); } @@ -1060,7 +1058,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().toEpochMilli())); + paidAt.put(payment.getDeliveryId(), Long.valueOf(payment.getCreatedAt())); } } Map couriers = new HashMap(); @@ -1254,7 +1252,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, Instant since) { + private boolean awaitsCharge(String customer, String methodId, long 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 6e061e83002..5b99403e1df 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,7 +48,6 @@ 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; @@ -183,8 +182,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(Instant.ofEpochMilli(now - END_RETRY_MILLIS)); - List left = leftBehind(Instant.ofEpochMilli(now - END_GRACE_MILLIS)); + dropEndedBefore(now - END_RETRY_MILLIS); + List left = leftBehind(now - END_GRACE_MILLIS); Exception failed = null; for (int iter = 0; iter < left.size(); iter++) { String id = left.get(iter).getDeliveryId(); @@ -205,13 +204,13 @@ public void endLeftBehind() throws IOException { } @Transactional - private void dropEndedBefore(Instant before) { - activities.dropEndedBefore(Instant.EPOCH, before); + private void dropEndedBefore(long before) { + activities.dropEndedBefore(before); } @Transactional(readOnly = true) - private List leftBehind(Instant before) { - return activities.leftBehind(Instant.EPOCH, before, new PageRequest(0, 50)); + private List leftBehind(long before) { + return activities.leftBehind(before, new PageRequest(0, 50)); } @Transactional @@ -281,11 +280,11 @@ public DeliveryActivityDto attach(String customer, String orderId, DeliveryActiv row.setDeliveryId(orderId); row.setUsername(customer); row.setActivityId(activityId); - row.setSentAt(Instant.now()); + row.setSentAt(System.currentTimeMillis()); activities.insert(row); } else { row.setActivityId(activityId); - row.setSentAt(Instant.now()); + row.setSentAt(System.currentTimeMillis()); } return new DeliveryActivityDto(activityId); } @@ -401,7 +400,7 @@ private List compose(String id, OrderState state) throws IOException { } // end::savor-push-messages[] if (!state.isActive() && activity != null) { - activities.markEnded(id, Instant.now(), Instant.EPOCH); + activities.markEnded(id, System.currentTimeMillis()); } if (toCustomer != null && !wants(customer, OrderState.DELIVERED == state)) { toCustomer = null; @@ -486,7 +485,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, Instant.ofEpochMilli(now), Instant.ofEpochMilli(now - activityMillis)) != 1) { + if (activities.claim(orderId, now, 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 cb4a9db6d83..30e63516f9a 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,7 +30,6 @@ import com.codenameone.examples.savor.repository.PushDeviceRepository; import java.io.IOException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -113,7 +112,7 @@ private void makeRoom(String username) { while (held.size() >= MAX_PER_ACCOUNT) { PushDevice oldest = held.get(0); for (PushDevice each : held) { - if (each.getUpdatedAt().isBefore(oldest.getUpdatedAt())) { + if (each.getUpdatedAt() < oldest.getUpdatedAt()) { oldest = each; } } @@ -152,7 +151,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(Instant.ofEpochMilli(now)); + row.setUpdatedAt(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 78091c4b52b..0a71b192ff4 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,7 +26,6 @@ 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. @@ -73,7 +72,7 @@ public interface CourierApplicationRepository extends CrudRepository :to") int approveUnlessApproved(@Param("username") String username, - @Param("to") String approved, @Param("at") Instant at, @Param("by") String by); + @Param("to") String approved, @Param("at") long 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. @@ -90,7 +89,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") Instant at); + @Param("to") String to, @Param("at") long 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 5148ee9b4b7..cf4fe3015a6 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,7 +26,6 @@ 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 @@ -59,7 +58,7 @@ public interface CourierDocumentRepository extends CrudRepository freeInBox(@Param("fresh") Instant fresh, @Param("south") double south, + List freeInBox(@Param("fresh") long 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); @@ -86,7 +85,7 @@ List freeInBox(@Param("fresh") Instant fresh, @Param("south") doub int takeOffLine(@Param("username") String username); /// The couriers on line who reported in at or after `seenSince`. - long countByOnlineTrueAndLastSeenGreaterThanEqual(Instant seenSince); + long countByOnlineTrueAndLastSeenGreaterThanEqual(long 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 e73d898ab97..43ab2087711 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,7 +27,6 @@ import com.codenameone.examples.savor.api.OrderState; import com.codenameone.examples.savor.domain.CustomerOrder; -import java.time.Instant; import java.util.List; /// Every order. @@ -45,16 +44,16 @@ List findTop50ByRestaurantIdAndStateInOrderByPlacedAtDesc(String OrderState[] states); List findByRestaurantIdAndStateAndDeliveredAtGreaterThanEqual(String restaurantId, - OrderState state, Instant since); + OrderState state, long since); - List findByStateAndPlacedAtLessThan(OrderState state, Instant before); + List findByStateAndPlacedAtLessThan(OrderState state, long before); - List findByStateAndAcceptedAtLessThan(OrderState state, Instant before); + List findByStateAndAcceptedAtLessThan(OrderState state, long before); boolean existsByCustomerAndMethodIdAndStateIn(String customer, String methodId, OrderState[] states); - List findByPaymentStatusAndUpdatedAtLessThan(String paymentStatus, Instant before); + List findByPaymentStatusAndUpdatedAtLessThan(String paymentStatus, long 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 @@ -63,12 +62,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") Instant before, PageRequest page); + @Param("statuses") String[] statuses, @Param("before") long before, PageRequest page); @Query("select o from CustomerOrder o order by o.placedAt desc") List newest(PageRequest page); - List findByPlacedAtGreaterThanEqual(Instant since); + List findByPlacedAtGreaterThanEqual(long since); long countByCustomerAndStateIn(String customer, OrderState[] states); @@ -79,54 +78,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") Instant now); + @Param("now") long 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") Instant now); + int paymentStatus(@Param("id") String id, @Param("status") String status, @Param("now") long 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") Instant now); + @Param("to") OrderState to, @Param("prep") int prep, @Param("now") long 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") Instant now); + @Param("to") OrderState to, @Param("now") long 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") Instant now); + @Param("to") OrderState to, @Param("now") long 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") Instant now); + @Param("to") OrderState to, @Param("reason") String reason, @Param("now") long 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") Instant now); + @Param("stars") int stars, @Param("now") long 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") Instant since); + List countByRestaurant(@Param("since") long since); - long countByPlacedAtGreaterThanEqual(Instant since); + long countByPlacedAtGreaterThanEqual(long since); long countByStateIn(OrderState[] states); @@ -138,7 +137,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") Instant since); + List countByState(@Param("since") long since); /// One row for each order placed since `since`: `{id, placedAt, state, /// totalCents, paymentStatus, deliveredAt}`. @@ -150,7 +149,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") Instant since); + List timeline(@Param("since") long 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 982a0364719..c4e42751c00 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,7 +26,6 @@ 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. @@ -41,27 +40,23 @@ public interface DeliveryActivityRepository extends CrudRepository :never and a.endedAt < :before " + @Query("select a from DeliveryActivity a where a.endedAt > 0 and a.endedAt < :before " + "order by a.endedAt") - List leftBehind(@Param("never") Instant never, @Param("before") Instant before, - PageRequest page); + List leftBehind(@Param("before") long before, PageRequest page); /// Forgets the activities whose delivery ended before `before`. @Modifying - @Query("delete from DeliveryActivity a where a.endedAt > :never and a.endedAt < :before") - int dropEndedBefore(@Param("never") Instant never, @Param("before") Instant before); + @Query("delete from DeliveryActivity a where a.endedAt > 0 and a.endedAt < :before") + int dropEndedBefore(@Param("before") long 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 0e30b71449f..30c49dfc92e 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,7 +25,6 @@ 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. @@ -43,5 +42,5 @@ public interface DeliveryEventRepository extends CrudRepository= :since)") - List reached(@Param("since") Instant since, @Param("state") DeliveryState state); + List reached(@Param("since") long 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 2512f7c304c..ddb775291aa 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,7 +27,6 @@ import com.codenameone.examples.savor.api.DeliveryState; import com.codenameone.examples.savor.domain.Delivery; -import java.time.Instant; import java.util.List; /// Deliveries. @@ -71,11 +70,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, Instant since, String methodId); + String customer, DeliveryState state, String paymentStatus, long since, String methodId); /// The same, to be charged to any method but `methodId`. boolean existsByCustomerAndStateAndPaymentStatusAndUpdatedAtGreaterThanAndMethodIdNot( - String customer, DeliveryState state, String paymentStatus, Instant since, String methodId); + String customer, DeliveryState state, String paymentStatus, long since, String methodId); /// A customer's deliveries whose payment is `paymentStatus` and that carry a tip. List findByCustomerAndPaymentStatusAndTipCentsGreaterThan(String customer, @@ -100,16 +99,16 @@ List findByCustomerAndStateOrderByRequestedAtDesc(String customer, Del List newest(PageRequest page); /// The deliveries in `state` whose offer ran out before `now`. - List findByStateAndOfferExpiresAtLessThan(DeliveryState state, Instant now); + List findByStateAndOfferExpiresAtLessThan(DeliveryState state, long 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, Instant since); + DeliveryState state, long since); - long countByRequestedAtGreaterThanEqual(Instant since); + long countByRequestedAtGreaterThanEqual(long since); long countByStateIn(DeliveryState[] states); @@ -127,14 +126,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") Instant now, @Param("customer") String customer); + @Param("to") DeliveryState to, @Param("now") long 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") Instant now, @Param("courier") String courier); + @Param("to") DeliveryState to, @Param("now") long now, @Param("courier") String courier); // tag::savor-delivery-move[] /// Takes an offer made to `courier`: refused once the offer has lapsed, as @@ -144,7 +143,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") Instant now, @Param("courier") String courier); + @Param("to") DeliveryState to, @Param("now") long now, @Param("courier") String courier); // end::savor-delivery-move[] /// Gives a delivery of `courier`'s back to be offered again, writing @@ -153,7 +152,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") Instant now, @Param("courier") String courier, + @Param("to") DeliveryState to, @Param("now") long now, @Param("courier") String courier, @Param("newCourier") String newCourier); /// Holds `customer`'s delivery while it is in one of `states`, answering 0 when @@ -173,15 +172,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") Instant now); + @Param("to") DeliveryState to, @Param("now") long 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") Instant now, @Param("courier") String courier, - @Param("expiresAt") Instant expiresAt); + @Param("to") DeliveryState to, @Param("now") long now, @Param("courier") String courier, + @Param("expiresAt") long expiresAt); // ----------------------------------------------------------- the rest @@ -202,7 +201,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") Instant after, @Param("before") Instant before, + List unsettled(@Param("after") long after, @Param("before") long before, PageRequest page); /// Records how the charge for a delivery came out. A statement of its own and @@ -264,13 +263,13 @@ List unsettled(@Param("after") Instant after, @Param("before") Instant @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") Instant since); + Object[] paidTotalsSince(@Param("courier") String courier, @Param("since") long 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") Instant since); + Long paidSince(@Param("courier") String courier, @Param("since") long 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 @@ -303,7 +302,7 @@ List unsettled(@Param("after") Instant after, @Param("before") Instant @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") Instant since); + List tipChargedSince(@Param("courier") String courier, @Param("since") long since); /// What customers paid in fares for deliveries in `state` whose payment is `paid`. @Query("select coalesce(sum(r.fareCents), 0) from Delivery r " @@ -313,17 +312,17 @@ List unsettled(@Param("after") Instant after, @Param("before") Instant /// 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") Instant since, @Param("state") DeliveryState state); + Long faresSince(@Param("since") long 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") Instant since); + List countByState(@Param("since") long 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") Instant since, @Param("state") DeliveryState state); + List countByCourier(@Param("since") long since, @Param("state") DeliveryState state); /// One row for each delivery asked for since `since`: `{id, requestedAt, /// state, fareCents, paymentStatus}`. @@ -336,7 +335,7 @@ List unsettled(@Param("after") Instant after, @Param("before") Instant /// 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") Instant since); + List timeline(@Param("since") long 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 88d51bbd62f..28eda4163e2 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,7 +21,6 @@ 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. @@ -34,7 +33,7 @@ public interface LiveTicketRepository extends CrudRepository int deleteByTicketHash(String ticketHash); /// Deletes the tickets that went stale before `now`. - int deleteByExpiresAtLessThan(Instant now); + int deleteByExpiresAtLessThan(long 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 2b7d5db2ee7..c26c87168d8 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,7 +24,6 @@ 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. @@ -33,7 +32,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 6f7c4e4a202..38dd2ce9c24 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,7 +24,6 @@ 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. @@ -43,7 +42,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") Instant at); + @Param("at") long 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 e0bbc2b43e8..9f6aa508e46 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,7 +24,6 @@ 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) @@ -40,7 +39,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") Instant since); + List signUps(@Param("since") long 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 060dbda2b2b..821c571194d 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,7 +36,6 @@ 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; @@ -92,8 +91,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(Instant.now()); - p.setLastSeen(Instant.now()); + p.setCreatedAt(Clock.now()); + p.setLastSeen(Clock.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 16e016b7819..61124b57830 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,7 +55,6 @@ 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; @@ -97,7 +96,7 @@ public AdminEndpoint(Accounts accounts, ProfileRepository profiles, MatchRecordR @Override @Transactional(readOnly = true) public AdminStatsDto stats() throws Exception { - Instant today = Instant.ofEpochMilli(Clock.dayOf(Clock.now())); + long today = Clock.dayOf(Clock.now()); int gems = 0; List sold = purchases.since(today); for (StorePurchase s : sold) { @@ -105,7 +104,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(Instant.now())), sold.size(), gems); + (int) count(profiles.suspended(Clock.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 dc848a877d7..b6778461f35 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,7 +35,6 @@ 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; @@ -116,7 +115,7 @@ Flag store(String username, String kind, String reason, String matchId, String r f.setReason(reason); f.setMatchId(matchId); f.setReporter(reporter); - f.setCreatedAt(Instant.now()); + f.setCreatedAt(Clock.now()); f.setPending(true); flags.insert(f); Profile p = profiles.findById(username); @@ -169,7 +168,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().toEpochMilli(), f.isPending()); + f.getKind(), f.getReason(), f.getMatchId(), f.getReporter(), f.getCreatedAt(), 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 265d12a3b46..418a5f3a1c6 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,7 +37,6 @@ 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; @@ -102,7 +101,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(Instant.now().plusMillis(days * Clock.DAY)); + p.setSuspendedUntil(Clock.now() + days * Clock.DAY); accounts.setEnabled(username, false); closes = true; } else if (BAN.equals(action)) { @@ -111,7 +110,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(Instant.EPOCH); + p.setSuspendedUntil(0); accounts.setEnabled(username, true); } else if (RESET_TROPHIES.equals(action)) { p.setTrophies(0); @@ -126,7 +125,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(Instant.now()); + a.setCreatedAt(Clock.now()); audit.insert(a); return closes; } @@ -141,9 +140,8 @@ public void liftExpired() { public int lift(long now) { int lifted = 0; for (Profile p : profiles.findAll()) { - if (!p.isBanned() && p.getSuspendedUntil().isAfter(Instant.EPOCH) - && p.getSuspendedUntil().toEpochMilli() <= now) { - p.setSuspendedUntil(Instant.EPOCH); + if (!p.isBanned() && p.getSuspendedUntil() > 0 && p.getSuspendedUntil() <= now) { + p.setSuspendedUntil(0); profiles.save(p); accounts.setEnabled(p.getUsername(), true); lifted++; @@ -166,7 +164,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().toEpochMilli())); + a.getCreatedAt())); } 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 253ca75d0b7..3d371e9559a 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,7 +21,6 @@ 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 @@ -43,7 +42,7 @@ public class AdminAction { private String reason = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public AdminAction() { } @@ -88,11 +87,11 @@ public void setReason(String reason) { this.reason = reason; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 a149cda2e3a..0530c15a4b4 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,7 +21,6 @@ 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 @@ -55,7 +54,7 @@ public class Broadcast { private String sentBy = ""; @Column(nullable = false) - private Instant sentAt = Instant.EPOCH; + private long sentAt; public Broadcast() { } @@ -132,11 +131,11 @@ public void setSentBy(String sentBy) { this.sentBy = sentBy; } - public Instant getSentAt() { + public long getSentAt() { return sentAt; } - public void setSentAt(Instant sentAt) { + public void setSentAt(long 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 10f3e3976d3..34d8b6d41f2 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,7 +21,6 @@ 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 @@ -46,7 +45,7 @@ public class Flag { private String reporter = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) private boolean pending; @@ -105,11 +104,11 @@ public void setReporter(String reporter) { this.reporter = reporter; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 42d97421f1c..f5e11a9f632 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,7 +21,6 @@ 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 @@ -52,7 +51,7 @@ public class ForgeAsset { private String data = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public ForgeAsset() { } @@ -121,11 +120,11 @@ public void setData(String data) { this.data = data; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 9d823f23415..e2c1f8ab013 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,7 +21,6 @@ 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. @@ -83,10 +82,10 @@ public class ForgePack { private boolean pendingAssets; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; public ForgePack() { } @@ -235,19 +234,19 @@ public void setPendingAssets(boolean pendingAssets) { this.pendingAssets = pendingAssets; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 cc7b5a2f3a0..c88fca804af 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,7 +21,6 @@ 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. @@ -44,7 +43,7 @@ public class ForgePackVersion { private String content = ""; @Column(nullable = false) - private Instant publishedAt = Instant.EPOCH; + private long publishedAt; public ForgePackVersion() { } @@ -89,11 +88,11 @@ public void setContent(String content) { this.content = content; } - public Instant getPublishedAt() { + public long getPublishedAt() { return publishedAt; } - public void setPublishedAt(Instant publishedAt) { + public void setPublishedAt(long 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 4d6779bc905..3155f92e400 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,7 +21,6 @@ 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 @@ -34,7 +33,7 @@ public class GameTicket { private String username = ""; @Column(nullable = false) - private Instant expiresAt = Instant.EPOCH; + private long expiresAt; public GameTicket() { } @@ -55,11 +54,11 @@ public void setUsername(String username) { this.username = username; } - public Instant getExpiresAt() { + public long getExpiresAt() { return expiresAt; } - public void setExpiresAt(Instant expiresAt) { + public void setExpiresAt(long 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 70077982f07..977ff589d67 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,7 +21,6 @@ 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 @@ -61,7 +60,7 @@ public class MatchRecord { private int ticks; @Column(nullable = false) - private Instant endedAt = Instant.EPOCH; + private long endedAt; @Column(nullable = false, type = "VARCHAR(16)") private String rulesVersion = ""; @@ -160,11 +159,11 @@ public void setTicks(int ticks) { this.ticks = ticks; } - public Instant getEndedAt() { + public long getEndedAt() { return endedAt; } - public void setEndedAt(Instant endedAt) { + public void setEndedAt(long 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 c72add2c1b9..51d64019762 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,7 +21,6 @@ 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 @@ -49,7 +48,7 @@ public class MissionStars { private int plays; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; public MissionStars() { } @@ -110,11 +109,11 @@ public void setPlays(int plays) { this.plays = plays; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 2eaeee1e657..7eeb8b2d099 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,7 +21,6 @@ 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`. @@ -62,7 +61,7 @@ public class Pipeline { private int reached; @Column(nullable = false) - private Instant lastRun = Instant.EPOCH; + private long lastRun; @Column(nullable = false, type = "VARCHAR(190)") private String createdBy = ""; @@ -155,11 +154,11 @@ public void setReached(int reached) { this.reached = reached; } - public Instant getLastRun() { + public long getLastRun() { return lastRun; } - public void setLastRun(Instant lastRun) { + public void setLastRun(long 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 825e22a5d20..730947c1b30 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,7 +21,6 @@ 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. @@ -38,7 +37,7 @@ public class PipelineHit { private String username = ""; @Column(nullable = false) - private Instant hitAt = Instant.EPOCH; + private long hitAt; public String getId() { return id; @@ -64,11 +63,11 @@ public void setUsername(String username) { this.username = username; } - public Instant getHitAt() { + public long getHitAt() { return hitAt; } - public void setHitAt(Instant hitAt) { + public void setHitAt(long 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 ce8ca0d36d9..91b48bbf849 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,7 +21,6 @@ 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 @@ -67,16 +66,16 @@ public class Profile { private boolean muted; @Column(nullable = false) - private Instant suspendedUntil = Instant.EPOCH; + private long suspendedUntil; @Column(nullable = false) private boolean banned; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) - private Instant lastSeen = Instant.EPOCH; + private long lastSeen; @Column(nullable = false) private long adDay; @@ -194,11 +193,11 @@ public void setMuted(boolean muted) { this.muted = muted; } - public Instant getSuspendedUntil() { + public long getSuspendedUntil() { return suspendedUntil; } - public void setSuspendedUntil(Instant suspendedUntil) { + public void setSuspendedUntil(long suspendedUntil) { this.suspendedUntil = suspendedUntil; } @@ -210,19 +209,19 @@ public void setBanned(boolean banned) { this.banned = banned; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } - public Instant getLastSeen() { + public long getLastSeen() { return lastSeen; } - public void setLastSeen(Instant lastSeen) { + public void setLastSeen(long 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 0626603248f..f61eafee87d 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,7 +21,6 @@ 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. /// @@ -47,7 +46,7 @@ public class PushDevice { private String platform = ""; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; public PushDevice() { } @@ -92,11 +91,11 @@ public void setPlatform(String platform) { this.platform = platform; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 916de9aea08..da3343c91a8 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,7 +21,6 @@ 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. @@ -53,10 +52,10 @@ public class Referral { private boolean rewarded; @Column(nullable = false) - private Instant joinedAt = Instant.EPOCH; + private long joinedAt; @Column(nullable = false) - private Instant playedAt = Instant.EPOCH; + private long playedAt; public Referral() { } @@ -125,19 +124,19 @@ public void setRewarded(boolean rewarded) { this.rewarded = rewarded; } - public Instant getJoinedAt() { + public long getJoinedAt() { return joinedAt; } - public void setJoinedAt(Instant joinedAt) { + public void setJoinedAt(long joinedAt) { this.joinedAt = joinedAt; } - public Instant getPlayedAt() { + public long getPlayedAt() { return playedAt; } - public void setPlayedAt(Instant playedAt) { + public void setPlayedAt(long 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 55faaeae845..52e674981e2 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,7 +21,6 @@ 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. @@ -35,7 +34,7 @@ public class ReferralCode { private String username = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public ReferralCode() { } @@ -56,11 +55,11 @@ public void setUsername(String username) { this.username = username; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 ec57f9279c1..36f0c791350 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,7 +21,6 @@ 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 @@ -43,7 +42,7 @@ public class Spotlight { private String updatedBy = ""; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; public Spotlight() { } @@ -88,11 +87,11 @@ public void setUpdatedBy(String updatedBy) { this.updatedBy = updatedBy; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 fab55e39ac5..3941f4203e3 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,7 +21,6 @@ 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 @@ -43,7 +42,7 @@ public class StorePurchase { private int gems; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public StorePurchase() { } @@ -88,11 +87,11 @@ public void setGems(int gems) { this.gems = gems; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 6f37bc1269a..940278c771f 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,7 +65,6 @@ 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; @@ -141,7 +140,7 @@ public void seedOfficial() throws IOException { p = new ForgePack(); p.setId(official.id); p.setOwner(SYSTEM); - p.setCreatedAt(Instant.now()); + p.setCreatedAt(Clock.now()); } else if (!SYSTEM.equals(p.getOwner())) { return; } @@ -227,7 +226,7 @@ public PackSummaryDto saveDraft(String username, String content) throws IOExcept p.setId(pack.id); p.setOwner(username); p.setStatus(DRAFT); - p.setCreatedAt(Instant.now()); + p.setCreatedAt(Clock.now()); fillDraft(p, pack, username); packs.insert(p); } else { @@ -264,7 +263,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(Instant.now()); + p.setUpdatedAt(Clock.now()); packs.save(p); return summary(p); } @@ -369,7 +368,7 @@ public AssetDto upload(String username, AssetUploadDto file) throws IOException if (a != null) { return asset(a, false); } - Instant since = Instant.now().minusMillis(Clock.DAY); + long since = Clock.now() - Clock.DAY; if (assets.countByOwnerAndCreatedAtGreaterThan(username, since) >= MAX_UPLOADS_PER_DAY) { throw new ResponseStatusException(429, "That is enough uploads for today"); } @@ -382,7 +381,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(Instant.now()); + a.setCreatedAt(Clock.now()); assets.insert(a); return asset(a, false); } @@ -449,7 +448,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(Instant.now()); + row.setUpdatedAt(Clock.now()); stars.save(row); p.setPlays(p.getPlays() + 1); packs.save(p); @@ -515,7 +514,7 @@ public PackSummaryDto packAction(String admin, String id, String action, String } else { throw new ResponseStatusException(400, "Unknown action"); } - p.setUpdatedAt(Instant.now()); + p.setUpdatedAt(Clock.now()); packs.save(p); record(admin, id, "PACK_" + action, reason); return summary(p); @@ -566,7 +565,7 @@ private void publishVersion(ForgePack p, ContentPack pack, boolean insert) throw v.setVersion(version); v.setHash(hash); v.setContent(canonical); - v.setPublishedAt(Instant.now()); + v.setPublishedAt(Clock.now()); versions.insert(v); p.setVersion(version); p.setHash(hash); @@ -579,7 +578,7 @@ private void publishVersion(ForgePack p, ContentPack pack, boolean insert) throw if (!HIDDEN.equals(p.getStatus())) { p.setStatus(PUBLISHED); } - p.setUpdatedAt(Instant.now()); + p.setUpdatedAt(Clock.now()); if (insert) { packs.insert(p); } else { @@ -660,7 +659,7 @@ private void fillDraft(ForgePack p, ContentPack pack, String username) throws IO p.setMissions(pack.missions.size()); p.setCards(pack.cards.size()); } - p.setUpdatedAt(Instant.now()); + p.setUpdatedAt(Clock.now()); } private static ContentPack parse(String content) { @@ -718,7 +717,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(Instant.now()); + a.setCreatedAt(Clock.now()); audit.insert(a); } @@ -738,7 +737,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().toEpochMilli()); + p.getRatingCount(), p.getMissions(), p.getCards(), p.isPendingAssets(), p.getUpdatedAt()); } 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 27e652595cb..ce07979d380 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().toEpochMilli(), m.getTicks())); + seat == 0 ? m.getTrophies0() : m.getTrophies1(), m.getEndedAt(), 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().toEpochMilli()); + m.getResult(), m.getCrowns0(), m.getCrowns1(), m.getReplay(), m.getRulesVersion(), m.getEndedAt()); } @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 149bfb0ae07..466e8db8bd4 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,7 +28,6 @@ import com.codenameone.examples.skirmish.repository.GameTicketRepository; import java.io.IOException; -import java.time.Instant; /// Tickets for the live channel. /// @@ -59,7 +58,7 @@ public TicketDto issue(String username) throws IOException { GameTicket row = new GameTicket(); row.setTicketHash(Ids.sha256(ticket)); row.setUsername(username); - row.setExpiresAt(Instant.now().plusMillis(TICKET_SECONDS * 1000L)); + row.setExpiresAt(System.currentTimeMillis() + TICKET_SECONDS * 1000L); tickets.insert(row); return new TicketDto(ticket, TICKET_SECONDS); } @@ -79,11 +78,11 @@ public String redeem(String ticket) throws IOException { return null; } String username = row.getUsername(); - Instant expiresAt = row.getExpiresAt(); + long 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.isBefore(Instant.now())) { + if (removed != 1 || expiresAt < System.currentTimeMillis()) { return null; } return username; @@ -93,7 +92,7 @@ public String redeem(String ticket) throws IOException { @Scheduled(fixedDelay = 60000, initialDelay = 60000) @Transactional public void sweep() throws IOException { - tickets.deleteByExpiresAtLessThan(Instant.now()); + tickets.deleteByExpiresAtLessThan(System.currentTimeMillis()); } /// 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 bc63b076cad..ec5c1485c6f 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,7 +35,6 @@ 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[] @@ -135,7 +134,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(Instant.now()); + p.setLastSeen(Clock.now()); progression.afterMatch(p, result == i, result == Match.DRAW, room.match.player(i).crowns(), cards[i], spells[i]); profiles.save(p); @@ -153,7 +152,7 @@ Outcome[] save(MatchRoom room) throws IOException { m.setTrophies0(out[0].trophies); m.setTrophies1(out[1].trophies); m.setTicks(room.match.tick()); - m.setEndedAt(Instant.now()); + m.setEndedAt(Clock.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 6509bb30565..e6a69f3e49a 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,7 +30,6 @@ import com.codenameone.examples.skirmish.repository.PushDeviceRepository; import java.io.IOException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -113,7 +112,7 @@ private void makeRoom(String username) { while (held.size() >= MAX_PER_ACCOUNT) { PushDevice oldest = held.get(0); for (PushDevice each : held) { - if (each.getUpdatedAt().isBefore(oldest.getUpdatedAt())) { + if (each.getUpdatedAt() < oldest.getUpdatedAt()) { oldest = each; } } @@ -152,7 +151,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(Instant.ofEpochMilli(now)); + row.setUpdatedAt(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 5686c2c7e47..4cc3112a94e 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,7 +23,6 @@ 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) @@ -31,5 +30,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(Instant since); + long countBySentAtGreaterThan(long 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 9a252a5160c..c18fe584309 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,7 +24,6 @@ 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) @@ -32,5 +31,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, Instant since); + long countByOwnerAndCreatedAtGreaterThan(String owner, long 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 ad1d9594f8b..f86069e9dd2 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,7 +21,6 @@ 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. @@ -34,7 +33,7 @@ public interface GameTicketRepository extends CrudRepository int deleteByTicketHash(String ticketHash); /// Deletes the tickets that went stale before `now`. - int deleteByExpiresAtLessThan(Instant now); + int deleteByExpiresAtLessThan(long 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 e9e8661499e..c94f09d57e7 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,7 +24,6 @@ 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) @@ -33,8 +32,8 @@ public interface MatchRecordRepository extends CrudRepository of(@Param("u") String username, PageRequest page); - long countByEndedAtGreaterThan(Instant since); + long countByEndedAtGreaterThan(long since); @Query("select m from MatchRecord m where m.endedAt >= :since") - List since(@Param("since") Instant since); + List since(@Param("since") long 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 c4f02bddf2d..e2c501941fc 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,7 +25,6 @@ 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) @@ -45,16 +44,15 @@ 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") Instant now); + Long suspended(@Param("now") long 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 `Instant.ofEpochMilli(Long.MAX_VALUE)` and - /// `Instant.ofEpochMilli(Long.MIN_VALUE)` to leave them out). + /// lapsed and the new (pass 0 and `Long.MAX_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") Instant seenBefore, @Param("joined") Instant joinedAfter, PageRequest page); + List audience(@Param("seen") long seenBefore, @Param("joined") long 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") Instant seenBefore, @Param("joined") Instant joinedAfter); + Long audienceSize(@Param("seen") long seenBefore, @Param("joined") long 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 2e9421728fd..ecff245a83d 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,7 +23,6 @@ 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) @@ -32,5 +31,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") Instant since); + List since(@Param("since") long 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 0e448019e2f..a9339f80a96 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,7 +33,6 @@ 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; @@ -137,7 +136,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(Instant.now()); + row.setCreatedAt(Clock.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 3d41e789b5a..39fd4e0b0ec 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().toEpochMilli()); + return days(now - p.getLastSeen()); case "daysSinceJoin": - return days(now - p.getCreatedAt().toEpochMilli()); + return days(now - p.getCreatedAt()); 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 bc56309d471..3830930bb64 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,7 +36,6 @@ 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; @@ -81,15 +80,15 @@ public InsightsDto report(int days) { List all = profiles.findAll(); int[] joined = new int[n]; for (Profile p : all) { - bump(joined, first, p.getCreatedAt().toEpochMilli()); + bump(joined, first, p.getCreatedAt()); } 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(Instant.ofEpochMilli(first))) { - int d = dayIndex(first, m.getEndedAt().toEpochMilli(), n); + for (MatchRecord m : matches.since(first)) { + int d = dayIndex(first, m.getEndedAt(), n); if (d >= 0) { battles[d]++; fought.get(d).add(m.getPlayer0()); @@ -107,10 +106,10 @@ public InsightsDto report(int days) { active[i] = fought.get(i).size(); } int[] gems = new int[n]; - List sales = purchases.since(Instant.EPOCH); + List sales = purchases.since(0); Set paid = new HashSet<>(); for (StorePurchase s : sales) { - int d = dayIndex(first, s.getCreatedAt().toEpochMilli(), n); + int d = dayIndex(first, s.getCreatedAt(), n); if (d >= 0) { gems[d] += s.getGems(); } @@ -150,9 +149,9 @@ private static List retention(List all, long now) { int cohort = 0; int back = 0; for (Profile p : all) { - if (p.getCreatedAt().toEpochMilli() <= now - span) { + if (p.getCreatedAt() <= now - span) { cohort++; - if (p.getLastSeen().toEpochMilli() - p.getCreatedAt().toEpochMilli() >= span) { + if (p.getLastSeen() - p.getCreatedAt() >= span) { back++; } } @@ -185,8 +184,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().isBefore(b.getLastSeen()) ? -1 - : a.getLastSeen().isAfter(b.getLastSeen()) ? 1 : a.getUsername().compareTo(b.getUsername())); + Collections.sort(found, (a, b) -> a.getLastSeen() < b.getLastSeen() ? -1 + : a.getLastSeen() > 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))); @@ -198,7 +197,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(Instant.EPOCH), referrals.findAll()); + return Audience.of(conditions, purchases.since(0), 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 f94cf3aed94..052009212fe 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,7 +36,6 @@ 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; @@ -109,7 +108,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().toEpochMilli() > now - p.getCooldownDays() * Clock.DAY) { + if (hit != null && hit.getHitAt() > now - p.getCooldownDays() * Clock.DAY) { continue; } if (GEMS.equals(p.getAction())) { @@ -121,10 +120,10 @@ public PipelineDto run(String id) throws IOException { hit.setId(key); hit.setPipeline(p.getId()); hit.setUsername(player.getUsername()); - hit.setHitAt(Instant.ofEpochMilli(now)); + hit.setHitAt(now); hits.insert(hit); } else { - hit.setHitAt(Instant.ofEpochMilli(now)); + hit.setHitAt(now); hits.save(hit); } due.add(player.getUsername()); @@ -136,7 +135,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(Instant.ofEpochMilli(now)); + p.setLastRun(now); pipelines.save(p); return dto(p); } @@ -240,7 +239,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().toEpochMilli()); + p.getScreen(), p.getAmount(), p.getCooldownDays(), p.getReached(), p.getLastRun()); } private void record(String admin, String action, String reason) throws IOException { @@ -250,7 +249,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(Instant.now()); + a.setCreatedAt(Clock.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 f4c6f5d8a45..e90013eca96 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,7 +40,6 @@ 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; @@ -122,7 +121,7 @@ public PromoteDto overview() throws IOException { sent.add(dto(b)); } return new PromoteDto((int) profiles.count(), - profiles.audienceSize(Instant.ofEpochMilli(Long.MAX_VALUE), Instant.ofEpochMilli(now - 7 * Clock.DAY)).intValue(), + profiles.audienceSize(Long.MAX_VALUE, now - 7 * Clock.DAY).intValue(), (int) referrals.count(), referrals.inState(Referrals.PLAYED).intValue(), top, sent, spotlightOf()); } @@ -139,7 +138,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(Instant.ofEpochMilli(now - Clock.DAY)) >= MAX_BROADCASTS_PER_DAY) { + if (broadcasts.countBySentAtGreaterThan(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"); } @@ -158,7 +157,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(Instant.ofEpochMilli(now)); + row.setSentAt(now); broadcasts.insert(row); record(admin, "BROADCAST", b.segment() + ": " + b.title().trim()); return dto(row); @@ -186,7 +185,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(Instant.now()); + row.setUpdatedAt(Clock.now()); if (fresh) { spotlights.insert(row); } else { @@ -199,7 +198,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().toEpochMilli()); + : new SpotlightDto(s.getMessage(), s.getPackId(), s.getScreen(), s.getUpdatedAt()); } private List audienceOf(BroadcastDto b) { @@ -217,8 +216,8 @@ private List audienceOf(BroadcastDto b) { return out; } long now = Clock.now(); - 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); + 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; for (int page = 0; out.size() < MAX_AUDIENCE; page++) { List rows = profiles.audience(seen, joined, new PageRequest(page, PAGE)); for (Profile p : rows) { @@ -269,7 +268,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().toEpochMilli()); + b.getCampaign(), b.getTargets(), b.getSentBy(), b.getSentAt()); } private void record(String admin, String action, String reason) throws IOException { @@ -279,7 +278,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(Instant.now()); + a.setCreatedAt(Clock.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 4c45b622668..bec0d5b9d74 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,7 +37,6 @@ 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; @@ -96,7 +95,7 @@ public InviteDto invite(String username) throws IOException { ReferralCode c = new ReferralCode(); c.setCode(code); c.setUsername(username); - c.setCreatedAt(Instant.now()); + c.setCreatedAt(Clock.now()); codes.insert(c); } else { code = mine.get(0).getCode(); @@ -126,7 +125,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().isBefore(Instant.now().minusMillis(CLAIM_DAYS * Clock.DAY))) { + if (p == null || p.getCreatedAt() < Clock.now() - CLAIM_DAYS * Clock.DAY) { throw new ResponseStatusException(400, "Invites count for new players only"); } Referral r = new Referral(); @@ -137,7 +136,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(Instant.now()); + r.setJoinedAt(Clock.now()); referrals.insert(r); Profile from = profiles.findById(inviter); pushes.friendJoined(inviter, p.getDisplayName()); @@ -155,7 +154,7 @@ public void played(String username) throws IOException { return; } r.setState(PLAYED); - r.setPlayedAt(Instant.now()); + r.setPlayedAt(Clock.now()); boolean pay = referrals.countByInviterAndRewardedTrue(r.getInviter()) < MAX_REWARDED; r.setRewarded(pay); referrals.save(r); @@ -174,7 +173,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().toEpochMilli())); + r.getJoinedAt())); } } 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 7308eb70487..533ae91da46 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,7 +43,6 @@ 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; @@ -153,7 +152,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, Instant.now()); + false, gender, System.currentTimeMillis()); if (request.driver() || request.wantsToDrive()) { applications.open(username, vehicle, plate); } @@ -168,7 +167,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], Instant.now()); + admin, GENDERS[0], System.currentTimeMillis()); } /// As the method above, for a caller that also knows the gender and when @@ -178,7 +177,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, Instant openedAt) throws IOException { + String gender, long openedAt) throws IOException { users.createUser(User.withUsername(username).password(encoder.encode(password)) .roles(roles(driver, admin)).build()); Profile profile = new Profile(); @@ -492,7 +491,7 @@ private void retire(String username) throws IOException { if (!closed.existsById(hash)) { ClosedAccount row = new ClosedAccount(); row.setUsernameHash(hash); - row.setClosedAt(Instant.now()); + row.setClosedAt(System.currentTimeMillis()); 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 7a7190b9614..e2a2ea122e4 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,7 +40,6 @@ import com.codenameone.examples.wayline.ride.Fares; import java.io.IOException; -import java.time.Instant; /// The accounts a server starts with. /// @@ -170,7 +169,7 @@ void flag(String username, String why, int daysAgo) throws IOException { profile.setFlagged(true); profile.setFlagReason(why); moderation.record(username, ADMIN, Moderation.FLAG, why, - Instant.now().minusMillis(daysAgo * Days.MILLIS)); + System.currentTimeMillis() - daysAgo * Days.MILLIS); } /// An admin, or the plainest kind of account. @@ -232,7 +231,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 { - Instant handedIn = Instant.now().minusMillis((daysAgo + 1) * Days.MILLIS); + long handedIn = System.currentTimeMillis() - (daysAgo + 1) * Days.MILLIS; DriverApplication form = forms.findById(username); form.setLegalName(name); form.setDateOfBirth("1988-04-12"); @@ -292,13 +291,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(Instant.now().minusMillis(daysAgo * Days.MILLIS)); + form.setSubmittedAt(System.currentTimeMillis() - 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 Instant opened(int daysAgo) { - return Instant.now().minusMillis(daysAgo * Days.MILLIS); + private static long opened(int daysAgo) { + return System.currentTimeMillis() - 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 844c4753e22..08d0a5c220d 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,7 +26,6 @@ import com.codenameone.examples.wayline.repository.ModerationEventRepository; import java.io.IOException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -58,16 +57,15 @@ 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. - 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); + Long newest = events.newest(username); + long after = newest == null ? 0L : newest.longValue() + 1L; + record(username, by, action, reason, Math.max(System.currentTimeMillis(), after)); } /// 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, Instant at) + public void record(String username, String by, String action, String reason, long at) throws IOException { String why = reason == null ? "" : reason.trim(); ModerationEvent event = new ModerationEvent(); @@ -87,8 +85,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().toEpochMilli(), row.getActor(), - row.getAction(), row.getReason())); + out.add(new ModerationEventDto(row.getCreatedAt(), 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 1c53c360b64..10ed791a384 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,7 +31,6 @@ 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. /// @@ -73,7 +72,7 @@ public PhoneChallengeDto start(String username) throws IOException { UserDto user = accounts.describe(username); String code = newCode(); String codeHash = hash(username, code); - store(username, codeHash, Instant.now()); + store(username, codeHash, System.currentTimeMillis()); try { sms.send(user.phone(), "Your Wayline code is " + code); } catch (IOException failed) { @@ -99,20 +98,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, Instant now) throws IOException { + void store(String username, String codeHash, long 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 && pending.getSentAt().plusSeconds(RESEND_SECONDS).isAfter(now)) { + if (pending != null && now - pending.getSentAt() < 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().isBefore(now) && pending.getAttempts() < MAX_ATTEMPTS) { + } else if (pending.getExpiresAt() >= 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()); @@ -120,11 +119,11 @@ void store(String username, String codeHash, Instant now) throws IOException { pending.setPreviousAttempts(pending.getAttempts()); } else { pending.setPreviousHash(""); - pending.setPreviousExpiresAt(Instant.EPOCH); + pending.setPreviousExpiresAt(0L); pending.setPreviousAttempts(0); } pending.setCodeHash(codeHash); - pending.setExpiresAt(now.plusSeconds(CODE_SECONDS)); + pending.setExpiresAt(now + CODE_SECONDS * 1000L); pending.setAttempts(0); pending.setSentAt(now); if (first) { @@ -149,7 +148,7 @@ void discard(String username, String codeHash) throws IOException { return; } if (pending.getPreviousHash().length() == 0 - || pending.getPreviousExpiresAt().isBefore(Instant.now())) { + || pending.getPreviousExpiresAt() < System.currentTimeMillis()) { codes.deleteById(username); return; } @@ -157,9 +156,9 @@ void discard(String username, String codeHash) throws IOException { pending.setExpiresAt(pending.getPreviousExpiresAt()); pending.setAttempts(pending.getPreviousAttempts()); pending.setPreviousHash(""); - pending.setPreviousExpiresAt(Instant.EPOCH); + pending.setPreviousExpiresAt(0L); pending.setPreviousAttempts(0); - pending.setSentAt(Instant.EPOCH); + pending.setSentAt(0L); } /// Checks the code the user typed. Answers 400 for a wrong or expired one @@ -187,7 +186,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().isBefore(Instant.now())) { + if (pending == null || pending.getExpiresAt() < System.currentTimeMillis()) { throw new ResponseStatusException(400, "That code has expired. Ask for a new one"); } if (pending.getAttempts() >= MAX_ATTEMPTS) { @@ -223,7 +222,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().isBefore(Instant.now()) + && pending.getPreviousExpiresAt() >= System.currentTimeMillis() && 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 7f15a0b03c3..c8a89ce9e44 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,7 +44,6 @@ 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; @@ -117,9 +116,8 @@ public AdminStatsDto dashboard() throws IOException { } } int online = (int) cars.countByOnlineTrueAndLastSeenGreaterThanEqual( - Instant.ofEpochMilli(now - Matcher.FRESH_MILLIS)); - int today = (int) rides.countByRequestedAtGreaterThanEqual( - Instant.ofEpochMilli(Days.start(now))); + now - Matcher.FRESH_MILLIS); + int today = (int) rides.countByRequestedAtGreaterThanEqual(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)); @@ -143,11 +141,10 @@ 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(); - Instant from = Instant.ofEpochMilli(since); - List timeline = rides.timeline(from); + List timeline = rides.timeline(since); for (int iter = 0; iter < timeline.size(); iter++) { Object[] ride = timeline.get(iter); - long at = millis(ride[1]); + long at = whole(ride[1]); RideState state = Rows.state(ride[2]); requestedAt.put(Rows.text(ride[0]), Long.valueOf(at)); int index = (int) ((at - since) / Days.MILLIS); @@ -169,7 +166,7 @@ public StatsSeriesDto series(int days) throws IOException { int[] byState = new int[STATES.length]; long completed = 0L; long finished = 0L; - List states = rides.countByState(from); + List states = rides.countByState(since); for (int iter = 0; iter < states.size(); iter++) { RideState state = Rows.state(states.get(iter)[0]); long count = whole(states.get(iter)[1]); @@ -186,7 +183,7 @@ public StatsSeriesDto series(int days) throws IOException { } } int[] byProduct = new int[Fares.PRODUCTS.length]; - List products = rides.countByProduct(from); + List products = rides.countByProduct(since); 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])) { @@ -195,12 +192,12 @@ public StatsSeriesDto series(int days) throws IOException { } } Map completedBy = new HashMap(); - List perDriver = rides.countByDriver(from, RideState.COMPLETED); + List perDriver = rides.countByDriver(since, 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(from, RideState.COMPLETED)); + long fareSum = Rows.number(rides.faresSince(since, RideState.COMPLETED)); List hours = new ArrayList(); for (int iter = 0; iter < byHour.length; iter++) { hours.add(Integer.valueOf(byHour[iter])); @@ -222,9 +219,9 @@ public StatsSeriesDto series(int days) throws IOException { double completionRate = finished == 0L ? 0d : Math.round(completed * 100d / finished) / 100d; - List signUps = profiles.signUps(from); + List signUps = profiles.signUps(since); for (int iter = 0; iter < signUps.size(); iter++) { - int index = (int) ((signUps.get(iter).toEpochMilli() - since) / Days.MILLIS); + int index = (int) ((signUps.get(iter).longValue() - since) / Days.MILLIS); if (index >= 0 && index < span) { dayNewUsers[index]++; } @@ -238,13 +235,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(from, RideState.ACCEPTED); + List waits = events.reached(since, 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, millis(waits.get(iter)[1]) - asked.longValue()); + waited += Math.max(0L, whole(waits.get(iter)[1]) - asked.longValue()); answered++; } } @@ -300,14 +297,6 @@ 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 ccc84fe5bdb..88afe0cfffd 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,7 +21,6 @@ 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. @@ -32,7 +31,7 @@ public class ClosedAccount { private String usernameHash = ""; @Column(nullable = false) - private Instant closedAt = Instant.EPOCH; + private long closedAt; public ClosedAccount() { } @@ -45,11 +44,11 @@ public void setUsernameHash(String usernameHash) { this.usernameHash = usernameHash; } - public Instant getClosedAt() { + public long getClosedAt() { return closedAt; } - public void setClosedAt(Instant closedAt) { + public void setClosedAt(long 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 939786f2446..7cc3acad6c8 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,7 +21,6 @@ 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 @@ -76,13 +75,13 @@ public class DriverApplication { private String rejectionReason = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) - private Instant submittedAt = Instant.EPOCH; + private long submittedAt; @Column(nullable = false) - private Instant reviewedAt = Instant.EPOCH; + private long reviewedAt; @Column(nullable = false, type = "VARCHAR(190)") private String reviewedBy = ""; @@ -218,27 +217,27 @@ public void setRejectionReason(String rejectionReason) { this.rejectionReason = rejectionReason; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } - public Instant getSubmittedAt() { + public long getSubmittedAt() { return submittedAt; } - public void setSubmittedAt(Instant submittedAt) { + public void setSubmittedAt(long submittedAt) { this.submittedAt = submittedAt; } - public Instant getReviewedAt() { + public long getReviewedAt() { return reviewedAt; } - public void setReviewedAt(Instant reviewedAt) { + public void setReviewedAt(long 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 565daaf0805..893c17c14f4 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,7 +21,6 @@ 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. @@ -42,7 +41,7 @@ public class DriverDocument { private String status = ""; @Column(nullable = false) - private Instant uploadedAt = Instant.EPOCH; + private long uploadedAt; @Column(nullable = false) private String data = ""; @@ -82,11 +81,11 @@ public void setStatus(String status) { this.status = status; } - public Instant getUploadedAt() { + public long getUploadedAt() { return uploadedAt; } - public void setUploadedAt(Instant uploadedAt) { + public void setUploadedAt(long 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 19e92bad01f..28a89341862 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,7 +21,6 @@ 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 @@ -43,7 +42,7 @@ public class DriverState { private double heading; @Column(nullable = false) - private Instant lastSeen = Instant.EPOCH; + private long lastSeen; @Column(nullable = false) private long ratingSum; @@ -99,11 +98,11 @@ public void setHeading(double heading) { this.heading = heading; } - public Instant getLastSeen() { + public long getLastSeen() { return lastSeen; } - public void setLastSeen(Instant lastSeen) { + public void setLastSeen(long 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 62847a03e56..64fa22794f3 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,7 +21,6 @@ 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 @@ -34,7 +33,7 @@ public class LiveTicket { private String username = ""; @Column(nullable = false) - private Instant expiresAt = Instant.EPOCH; + private long expiresAt; public LiveTicket() { } @@ -55,11 +54,11 @@ public void setUsername(String username) { this.username = username; } - public Instant getExpiresAt() { + public long getExpiresAt() { return expiresAt; } - public void setExpiresAt(Instant expiresAt) { + public void setExpiresAt(long 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 b6509c576c8..56cf4f985eb 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,7 +21,6 @@ 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 @@ -34,7 +33,7 @@ public class ModerationEvent { private String username = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(190)") private String actor = ""; @@ -64,11 +63,11 @@ public void setUsername(String username) { this.username = username; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 84e32e0d6b8..5fffb1fe321 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,7 +21,6 @@ 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 @@ -43,7 +42,7 @@ public class Payment { private String providerRef = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(64)") private String tipRef = ""; @@ -58,7 +57,7 @@ public class Payment { private String refundReason = ""; @Column(nullable = false) - private Instant refundedAt = Instant.EPOCH; + private long refundedAt; public Payment() { } @@ -103,11 +102,11 @@ public void setProviderRef(String providerRef) { this.providerRef = providerRef; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } @@ -143,11 +142,11 @@ public void setRefundReason(String refundReason) { this.refundReason = refundReason; } - public Instant getRefundedAt() { + public long getRefundedAt() { return refundedAt; } - public void setRefundedAt(Instant refundedAt) { + public void setRefundedAt(long 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 8ce68550890..45f6f0e8ec5 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,7 +21,6 @@ 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. @@ -53,7 +52,7 @@ public class PaymentMethod { private boolean preferred; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public PaymentMethod() { } @@ -122,11 +121,11 @@ public void setPreferred(boolean preferred) { this.preferred = preferred; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 595124dfb85..22a6a37ad10 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,7 +21,6 @@ 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 @@ -37,7 +36,7 @@ public class PaymentSetup { private String reference = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false) private boolean completed; @@ -69,11 +68,11 @@ public void setReference(String reference) { this.reference = reference; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 46b49521a8d..0a1ebaa393c 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,7 +21,6 @@ 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 @@ -40,7 +39,7 @@ public class Payout { private String status = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(120)") private String destination = ""; @@ -80,11 +79,11 @@ public void setStatus(String status) { this.status = status; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 c3bed31bb96..8547e5f09a4 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,7 +21,6 @@ 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 @@ -34,20 +33,20 @@ public class PhoneCode { private String codeHash = ""; @Column(nullable = false) - private Instant expiresAt = Instant.EPOCH; + private long expiresAt; @Column(nullable = false) private int attempts; @Column(nullable = false) - private Instant sentAt = Instant.EPOCH; + private long sentAt; /// 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 Instant previousExpiresAt = Instant.EPOCH; + private long previousExpiresAt; /// 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. @@ -73,11 +72,11 @@ public void setCodeHash(String codeHash) { this.codeHash = codeHash; } - public Instant getExpiresAt() { + public long getExpiresAt() { return expiresAt; } - public void setExpiresAt(Instant expiresAt) { + public void setExpiresAt(long expiresAt) { this.expiresAt = expiresAt; } @@ -89,11 +88,11 @@ public void setAttempts(int attempts) { this.attempts = attempts; } - public Instant getSentAt() { + public long getSentAt() { return sentAt; } - public void setSentAt(Instant sentAt) { + public void setSentAt(long sentAt) { this.sentAt = sentAt; } @@ -105,11 +104,11 @@ public void setPreviousHash(String previousHash) { this.previousHash = previousHash; } - public Instant getPreviousExpiresAt() { + public long getPreviousExpiresAt() { return previousExpiresAt; } - public void setPreviousExpiresAt(Instant previousExpiresAt) { + public void setPreviousExpiresAt(long 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 df169909ed4..f9c57e3bae9 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,7 +21,6 @@ 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 @@ -58,7 +57,7 @@ public class Pricing { private double xl; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; @Column(nullable = false, type = "VARCHAR(190)") private String updatedBy = ""; @@ -146,11 +145,11 @@ public void setXl(double xl) { this.xl = xl; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 3576a87c28c..e58122895bb 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,7 +21,6 @@ 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. /// @@ -49,7 +48,7 @@ public class Profile { private String plate = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; @Column(nullable = false, type = "VARCHAR(16)") private String gender = "unspecified"; @@ -126,11 +125,11 @@ public void setPlate(String plate) { this.plate = plate; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 fb84f6e8cc2..88f00470019 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,7 +21,6 @@ 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. /// @@ -47,7 +46,7 @@ public class PushDevice { private String platform = ""; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; public PushDevice() { } @@ -92,11 +91,11 @@ public void setPlatform(String platform) { this.platform = platform; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long 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 aba0a2ce4ae..02537248968 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,7 +22,6 @@ 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. @@ -76,16 +75,16 @@ public class Ride { private double durationSeconds; @Column(nullable = false) - private Instant requestedAt = Instant.EPOCH; + private long requestedAt; @Column(nullable = false) - private Instant updatedAt = Instant.EPOCH; + private long updatedAt; @Column(nullable = false) - private Instant offerExpiresAt = Instant.EPOCH; + private long offerExpiresAt; @Column(nullable = false) - private Instant searchUntil = Instant.EPOCH; + private long searchUntil; @Column(nullable = false, type = "SMALLINT") private int stars; @@ -252,35 +251,35 @@ public void setDurationSeconds(double durationSeconds) { this.durationSeconds = durationSeconds; } - public Instant getRequestedAt() { + public long getRequestedAt() { return requestedAt; } - public void setRequestedAt(Instant requestedAt) { + public void setRequestedAt(long requestedAt) { this.requestedAt = requestedAt; } - public Instant getUpdatedAt() { + public long getUpdatedAt() { return updatedAt; } - public void setUpdatedAt(Instant updatedAt) { + public void setUpdatedAt(long updatedAt) { this.updatedAt = updatedAt; } - public Instant getOfferExpiresAt() { + public long getOfferExpiresAt() { return offerExpiresAt; } - public void setOfferExpiresAt(Instant offerExpiresAt) { + public void setOfferExpiresAt(long offerExpiresAt) { this.offerExpiresAt = offerExpiresAt; } - public Instant getSearchUntil() { + public long getSearchUntil() { return searchUntil; } - public void setSearchUntil(Instant searchUntil) { + public void setSearchUntil(long 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 a81a5bd26d2..1267299dc02 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,7 +21,6 @@ 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 @@ -39,12 +38,12 @@ public class RideActivity { /// When the server last sent it a state, for spacing out the updates. @Column(nullable = false) - private Instant sentAt = Instant.EPOCH; + private long sentAt; /// 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 Instant endedAt = Instant.EPOCH; + private long endedAt; public RideActivity() { } @@ -73,19 +72,19 @@ public void setActivityId(String activityId) { this.activityId = activityId; } - public Instant getSentAt() { + public long getSentAt() { return sentAt; } - public void setSentAt(Instant sentAt) { + public void setSentAt(long sentAt) { this.sentAt = sentAt; } - public Instant getEndedAt() { + public long getEndedAt() { return endedAt; } - public void setEndedAt(Instant endedAt) { + public void setEndedAt(long 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 134411957ce..4f96ce29a5a 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,7 +22,6 @@ 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 @@ -41,7 +40,7 @@ public class RideEvent { private String actor = ""; @Column(nullable = false) - private Instant createdAt = Instant.EPOCH; + private long createdAt; public RideEvent() { } @@ -78,11 +77,11 @@ public void setActor(String actor) { this.actor = actor; } - public Instant getCreatedAt() { + public long getCreatedAt() { return createdAt; } - public void setCreatedAt(Instant createdAt) { + public void setCreatedAt(long 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 b084ccd10a1..814a136912f 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,7 +47,6 @@ 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; @@ -148,7 +147,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"); } - Instant now = Instant.now(); + long now = System.currentTimeMillis(); 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 @@ -157,8 +156,7 @@ 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.toEpochMilli() - state.getLastSeen().toEpochMilli() : 0L; + long since = state != null && state.isOnline() ? now - state.getLastSeen() : 0L; boolean first = state == null; if (first) { state = new DriverState(); @@ -179,7 +177,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.toEpochMilli() - since, now.toEpochMilli()); + long[] days = Days.split(now - since, now); for (int iter = 0; iter < days.length; iter += 2) { addHours(driver, days[iter], days[iter + 1]); } @@ -284,11 +282,10 @@ 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, Instant.ofEpochMilli(now - now % DAY_MILLIS)); + Object[] day = rides.paidTotalsSince(driver, 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, Instant.ofEpochMilli(now - 7 * DAY_MILLIS))); + long week = Rows.number(rides.paidSince(driver, 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]); @@ -312,7 +309,7 @@ private static DriverDto toDto(Profile profile, DriverApplication application, double rating = 5d; long lastSeen = 0L; if (car != null) { - lastSeen = car.getLastSeen().toEpochMilli(); + lastSeen = car.getLastSeen(); // 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 f1ecda06185..500767060fe 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,7 +48,6 @@ 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; @@ -111,16 +110,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, Instant.ofEpochMilli(monthStart)); + RideState.COMPLETED, 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, Instant.ofEpochMilli(monthStart))); + rides.tipChargedSince(driver, monthStart)); for (int iter = 0; iter < done.size(); iter++) { Ride ride = done.get(iter); - long at = ride.getUpdatedAt().toEpochMilli(); + long at = ride.getUpdatedAt(); 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 @@ -193,7 +192,7 @@ public PayoutDto cashOut(String driver) throws IOException { row.setDriver(driver); row.setAmountCents(amount); row.setStatus("paid"); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); row.setDestination(account.getBankName() + " ****" + account.getLast4()); payouts.insert(row); return toDto(row); @@ -292,6 +291,6 @@ private static PayoutAccountDto toDto(PayoutAccount row) { private static PayoutDto toDto(Payout row) { return new PayoutDto(row.getId(), row.getAmountCents(), row.getStatus(), - row.getCreatedAt().toEpochMilli(), row.getDestination()); + row.getCreatedAt(), 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 0831bcf2439..3a7e343e68a 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,7 +45,6 @@ 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; @@ -255,7 +254,7 @@ public DriverApplicationDto upload(String username, DocumentUploadDto upload) // looked at the one it replaced. hold(username); editable(username); - Instant now = Instant.now(); + 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) { @@ -326,7 +325,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, Instant.now()); + applications.submit(username, was, PENDING, System.currentTimeMillis()); return get(username); } @@ -440,7 +439,7 @@ public void grant(String by, String username) throws IOException { applications.insert(blank(username, APPROVED, "", "")); return; } - applications.approveUnlessApproved(username, APPROVED, Instant.now(), by); + applications.approveUnlessApproved(username, APPROVED, System.currentTimeMillis(), by); } /// Takes the approval back, when an admin withdraws the DRIVER role. The @@ -448,7 +447,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", - Instant.now(), by); + System.currentTimeMillis(), by); } /// Everything kept about an account's application, for an account being @@ -469,7 +468,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, Instant.now(), by) + if (applications.move(username, PENDING, to, reason, System.currentTimeMillis(), by) != 1) { throw new ResponseStatusException(409, "That application is not waiting for an answer"); } @@ -544,7 +543,7 @@ private DriverApplication editable(String username) { /// moment it was made. private static DriverApplication blank(String username, String status, String vehicle, String plate) { - Instant now = Instant.now(); + long now = System.currentTimeMillis(); DriverApplication application = new DriverApplication(); application.setUsername(username); application.setStatus(status); @@ -553,7 +552,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 : Instant.EPOCH); + application.setReviewedAt(APPROVED.equals(status) ? now : 0L); return application; } @@ -585,10 +584,7 @@ private static DriverApplicationDto toDto(String username, String name, if (KINDS[kind].equals(stored[from])) { status = (String) stored[from + 1]; Object at = stored[from + 2]; - if (!(at instanceof Instant)) { - throw new IllegalStateException("Not a time: " + at); - } - uploadedAt = ((Instant) at).toEpochMilli(); + uploadedAt = at instanceof Number ? ((Number) at).longValue() : 0L; } } listed.add(new DocumentDto(KINDS[kind], status, uploadedAt)); @@ -603,8 +599,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().toEpochMilli(), - row.getReviewedAt().toEpochMilli(), row.getReviewedBy()); + row.getRejectionReason(), row.getSubmittedAt(), row.getReviewedAt(), + 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 f6120900547..e902411ff0d 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,7 +28,6 @@ import com.codenameone.examples.wayline.repository.LiveTicketRepository; import java.io.IOException; -import java.time.Instant; /// Tickets for the live channel. /// @@ -59,7 +58,7 @@ public TicketDto issue(String username) throws IOException { LiveTicket row = new LiveTicket(); row.setTicketHash(Ids.sha256(ticket)); row.setUsername(username); - row.setExpiresAt(Instant.now().plusSeconds(TICKET_SECONDS)); + row.setExpiresAt(System.currentTimeMillis() + TICKET_SECONDS * 1000L); tickets.insert(row); return new TicketDto(ticket, TICKET_SECONDS); } @@ -79,11 +78,11 @@ public String redeem(String ticket) throws IOException { return null; } String username = row.getUsername(); - Instant expiresAt = row.getExpiresAt(); + long 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.isBefore(Instant.now())) { + if (removed != 1 || expiresAt < System.currentTimeMillis()) { return null; } return username; @@ -93,7 +92,7 @@ public String redeem(String ticket) throws IOException { @Scheduled(fixedDelay = 60000, initialDelay = 60000) @Transactional public void sweep() throws IOException { - tickets.deleteByExpiresAtLessThan(Instant.now()); + tickets.deleteByExpiresAtLessThan(System.currentTimeMillis()); } /// 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 629812f11c4..04a4b247ab4 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,7 +45,6 @@ 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; @@ -197,7 +196,7 @@ private String customerForSetup(String username) { /// that are neither finished nor abandoned. private void refuseTooManySetups(String username) { if (setups.countByUsernameAndCompletedFalseAndCreatedAtGreaterThan(username, - Instant.now().minusMillis(SETUP_MILLIS)) >= MAX_OPEN_SETUPS) { + System.currentTimeMillis() - SETUP_MILLIS) >= MAX_OPEN_SETUPS) { throw new ResponseStatusException(429, "Too many cards are being added. Finish one, or try again later"); } @@ -214,7 +213,7 @@ private void refuseTooManySetups(String username) { @Transactional public void sweepSetups() throws IOException { setups.deleteByCompletedTrue(); - setups.deleteByCreatedAtLessThan(Instant.now().minusMillis(2L * SETUP_MILLIS)); + setups.deleteByCreatedAtLessThan(System.currentTimeMillis() - 2L * SETUP_MILLIS); } /// Keeps the reference the processor made for a rider on first use, and @@ -262,7 +261,7 @@ private void keepSetup(String username, String id, String reference) { row.setId(id); row.setUsername(username); row.setReference(reference); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); row.setCompleted(false); setups.insert(row); } @@ -325,7 +324,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().isBefore(Instant.now().minusMillis(SETUP_MILLIS))) { + || setup.getCreatedAt() < System.currentTimeMillis() - SETUP_MILLIS) { throw new ResponseStatusException(404, "No such card setup"); } PaymentCustomer customer = customers.findById(username); @@ -354,8 +353,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. - Instant newest = cards.newestAt(username); - Instant now = Instant.now(); + Long newest = cards.newestAt(username); + long after = newest == null ? 0L : newest.longValue() + 1L; PaymentMethod row = new PaymentMethod(); row.setId(id); row.setUsername(username); @@ -365,7 +364,7 @@ private PaymentMethodDto keepCard(String username, String setupId, String id, row.setExpYear(card.expYear); row.setToken(card.token); row.setPreferred(first); - row.setCreatedAt(newest != null && !newest.isBefore(now) ? newest.plusMillis(1L) : now); + row.setCreatedAt(Math.max(System.currentTimeMillis(), after)); cards.insert(row); return card(row); } @@ -492,8 +491,8 @@ public void forget(String username) throws IOException { } } - private static Instant retriedSince() { - return Instant.now().minusMillis(RETRY_MILLIS); + private static long retriedSince() { + return System.currentTimeMillis() - RETRY_MILLIS; } // --------------------------------------------------------------- charges @@ -557,7 +556,7 @@ private void keepPayment(String rideId, long amount, String currency, String sta row.setCurrency(currency); row.setStatus(status); row.setProviderRef(reference); - row.setCreatedAt(Instant.now()); + row.setCreatedAt(System.currentTimeMillis()); payments.insert(row); } @@ -751,7 +750,7 @@ private List refundsPending() { @Transactional private Ride endRefund(String rideId, String outcome) { if (payments.endRefund(rideId, outcome, - REFUNDED.equals(outcome) ? Instant.now() : Instant.EPOCH) != 1) { + REFUNDED.equals(outcome) ? System.currentTimeMillis() : 0L) != 1) { return null; } rides.paymentStatus(rideId, outcome); @@ -873,7 +872,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 ? Instant.EPOCH : Instant.now()); + payment.setRefundedAt(pending ? 0L : System.currentTimeMillis()); } /// Records a refund of the fare whose tip could not be refunded: the ride @@ -886,7 +885,7 @@ private void keepPartialRefund(String rideId, PaymentProvider.Refund fare, Strin payment.setRefundRef(cut(fare.reference, 64)); payment.setTipRefundRef(""); payment.setRefundReason(reason); - payment.setRefundedAt(Instant.EPOCH); + payment.setRefundedAt(0L); } // -------------------------------------------------------------- receipts @@ -918,7 +917,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().toEpochMilli(), admin, + return receipt(ride, payment == null ? 0L : payment.getCreatedAt(), admin, new HashMap()); } @@ -935,8 +934,7 @@ 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().toEpochMilli())); + paidAt.put(payment.getRideId(), Long.valueOf(payment.getCreatedAt())); } } Map drivers = new HashMap(); @@ -1099,7 +1097,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, Instant since) { + private boolean awaitsCharge(String rider, String methodId, long 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 2acda4d33fe..37fe75b134b 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,7 +30,6 @@ import com.codenameone.examples.wayline.repository.PushDeviceRepository; import java.io.IOException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; @@ -60,7 +59,7 @@ public PushDevices(PushDeviceRepository devices, ProfileRepository profiles) { public PushDeviceDto register(String username, PushDeviceDto device) throws IOException { PushTarget target = target(device); String id = key(target); - Instant now = Instant.now(); + long now = System.currentTimeMillis(); // 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. @@ -111,7 +110,7 @@ private void makeRoom(String username) { while (held.size() >= MAX_PER_ACCOUNT) { PushDevice oldest = held.get(0); for (PushDevice each : held) { - if (each.getUpdatedAt().isBefore(oldest.getUpdatedAt())) { + if (each.getUpdatedAt() < oldest.getUpdatedAt()) { oldest = each; } } @@ -147,7 +146,7 @@ List targetsOf(String username) { } // end::wayline-push-devices[] - private static void fill(PushDevice row, String username, PushDeviceDto device, Instant now) { + 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); 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 4ebcb84a229..a1a6788db68 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,7 +43,6 @@ 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; @@ -152,9 +151,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 { - Instant now = Instant.now(); - dropEndedBefore(now.minusMillis(END_RETRY_MILLIS)); - List left = leftBehind(now.minusMillis(END_GRACE_MILLIS)); + long now = System.currentTimeMillis(); + dropEndedBefore(now - END_RETRY_MILLIS); + List left = leftBehind(now - END_GRACE_MILLIS); Exception failed = null; for (int iter = 0; iter < left.size(); iter++) { String id = left.get(iter).getRideId(); @@ -175,13 +174,13 @@ public void endLeftBehind() throws IOException { } @Transactional - private void dropEndedBefore(Instant before) { - activities.dropEndedBefore(before, Instant.EPOCH); + private void dropEndedBefore(long before) { + activities.dropEndedBefore(before); } @Transactional(readOnly = true) - private List leftBehind(Instant before) { - return activities.leftBehind(before, Instant.EPOCH, new PageRequest(0, 50)); + private List leftBehind(long before) { + return activities.leftBehind(before, new PageRequest(0, 50)); } @Transactional @@ -253,11 +252,11 @@ public RideActivityDto attach(String rider, String rideId, RideActivityDto activ row.setRideId(rideId); row.setUsername(rider); row.setActivityId(activityId); - row.setSentAt(Instant.now()); + row.setSentAt(System.currentTimeMillis()); activities.insert(row); } else { row.setActivityId(activityId); - row.setSentAt(Instant.now()); + row.setSentAt(System.currentTimeMillis()); } return new RideActivityDto(activityId); } @@ -377,7 +376,7 @@ private List compose(String id, RideState state, String rider, String } // end::wayline-push-messages[] if (!state.isActive() && activity != null) { - activities.markEnded(id, Instant.now(), Instant.EPOCH); + activities.markEnded(id, System.currentTimeMillis()); } if (toRider != null && !wants(rider, RideState.COMPLETED == state)) { toRider = null; @@ -424,10 +423,10 @@ private List moved(String rideId, double lat, double lng) throws IOExc if (activity == null) { return out; } - Instant now = Instant.now(); + long now = System.currentTimeMillis(); // A conditional update, so that two reports arriving together send one // update between them. - if (activities.claim(rideId, now, now.minusMillis(activityMillis)) != 1) { + if (activities.claim(rideId, now, now - 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 3d4b5e02329..45aea747af3 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,7 +26,6 @@ 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. @@ -73,7 +72,7 @@ public interface DriverApplicationRepository extends CrudRepository :to") int approveUnlessApproved(@Param("username") String username, - @Param("to") String approved, @Param("at") Instant at, @Param("by") String by); + @Param("to") String approved, @Param("at") long 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. @@ -90,7 +89,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") Instant at); + @Param("to") String to, @Param("at") long 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 535816440bd..63015ad1e33 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,7 +26,6 @@ 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 @@ -59,7 +58,7 @@ public interface DriverDocumentRepository extends CrudRepository freeInBox(@Param("fresh") Instant fresh, @Param("south") double south, + List freeInBox(@Param("fresh") long 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); @@ -86,7 +85,7 @@ List freeInBox(@Param("fresh") Instant fresh, @Param("south") doubl int takeOffLine(@Param("username") String username); /// The drivers on line who reported in at or after `seenSince`. - long countByOnlineTrueAndLastSeenGreaterThanEqual(Instant seenSince); + long countByOnlineTrueAndLastSeenGreaterThanEqual(long 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 44ae5c711de..1b84547ab97 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,7 +21,6 @@ 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. @@ -34,7 +33,7 @@ public interface LiveTicketRepository extends CrudRepository int deleteByTicketHash(String ticketHash); /// Deletes the tickets that went stale before `now`. - int deleteByExpiresAtLessThan(Instant now); + int deleteByExpiresAtLessThan(long 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 a7fbfe21c57..680e8f19138 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,7 +24,6 @@ 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. @@ -33,7 +32,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 7b1b104e8cb..01b1646738e 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,7 +24,6 @@ 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. @@ -43,7 +42,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") Instant at); + @Param("at") long 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 a5feb7268e4..e81e7c95c63 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,7 +24,6 @@ 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) @@ -40,7 +39,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") Instant since); + List signUps(@Param("since") long 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 efe7ae4c33a..5e0a7c64c84 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,7 +26,6 @@ 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. @@ -41,26 +40,23 @@ public interface RideActivityRepository extends CrudRepository :none and a.endedAt < :before " + @Query("select a from RideActivity a where a.endedAt > 0 and a.endedAt < :before " + "order by a.endedAt") - List leftBehind(@Param("before") Instant before, @Param("none") Instant none, - PageRequest page); + List leftBehind(@Param("before") long before, PageRequest page); /// Forgets the activities whose ride ended before `before`. @Modifying - @Query("delete from RideActivity a where a.endedAt > :none and a.endedAt < :before") - int dropEndedBefore(@Param("before") Instant before, @Param("none") Instant none); + @Query("delete from RideActivity a where a.endedAt > 0 and a.endedAt < :before") + int dropEndedBefore(@Param("before") long before); } 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 9baef41d178..dc9ca139a6f 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,7 +25,6 @@ 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. @@ -43,5 +42,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") Instant since, @Param("state") RideState state); + List reached(@Param("since") long 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 411bfa8fcac..19e7a1fce90 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,7 +27,6 @@ import com.codenameone.examples.wayline.api.RideState; import com.codenameone.examples.wayline.domain.Ride; -import java.time.Instant; import java.util.List; /// Rides. @@ -71,11 +70,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, Instant since, String methodId); + String rider, RideState state, String paymentStatus, long since, String methodId); /// The same, to be charged to any method but `methodId`. boolean existsByRiderAndStateAndPaymentStatusAndUpdatedAtGreaterThanAndMethodIdNot( - String rider, RideState state, String paymentStatus, Instant since, String methodId); + String rider, RideState state, String paymentStatus, long since, String methodId); /// A rider's rides whose payment is `paymentStatus` and that carry a tip. List findByRiderAndPaymentStatusAndTipCentsGreaterThan(String rider, @@ -100,18 +99,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, Instant now); + List findByStateAndOfferExpiresAtLessThan(RideState state, long 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, Instant since); + RideState state, long since); long countByDriverAndState(String driver, RideState state); - long countByRequestedAtGreaterThanEqual(Instant since); + long countByRequestedAtGreaterThanEqual(long since); long countByStateIn(RideState[] states); @@ -129,14 +128,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") Instant now, @Param("rider") String rider); + @Param("to") RideState to, @Param("now") long 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") Instant now, @Param("driver") String driver); + @Param("to") RideState to, @Param("now") long now, @Param("driver") String driver); // tag::wayline-ride-move[] /// Takes an offer made to `driver`: refused once the offer has lapsed, as @@ -146,7 +145,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") Instant now, @Param("driver") String driver); + @Param("to") RideState to, @Param("now") long now, @Param("driver") String driver); // end::wayline-ride-move[] /// Gives a ride of `driver`'s back to be offered again, writing @@ -155,7 +154,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") Instant now, @Param("driver") String driver, + @Param("to") RideState to, @Param("now") long now, @Param("driver") String driver, @Param("newDriver") String newDriver); /// Holds `rider`'s ride while it is in one of `states`, answering 0 when @@ -175,15 +174,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") Instant now); + @Param("to") RideState to, @Param("now") long 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") Instant now, @Param("driver") String driver, - @Param("expiresAt") Instant expiresAt); + @Param("to") RideState to, @Param("now") long now, @Param("driver") String driver, + @Param("expiresAt") long expiresAt); // ----------------------------------------------------------- the rest @@ -201,7 +200,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") Instant after, @Param("before") Instant before, + List unsettled(@Param("after") long after, @Param("before") long before, PageRequest page); /// Records how the charge for a ride came out. A statement of its own and @@ -263,13 +262,13 @@ List unsettled(@Param("after") Instant after, @Param("before") Instant bef @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") Instant since); + Object[] paidTotalsSince(@Param("driver") String driver, @Param("since") long 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") Instant since); + Long paidSince(@Param("driver") String driver, @Param("since") long 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 @@ -296,7 +295,7 @@ List unsettled(@Param("after") Instant after, @Param("before") Instant bef @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") Instant since); + List tipChargedSince(@Param("driver") String driver, @Param("since") long since); /// What riders paid in fares for rides in `state` whose payment is `paid`. @Query("select coalesce(sum(r.fareCents), 0) from Ride r " @@ -306,22 +305,22 @@ List unsettled(@Param("after") Instant after, @Param("before") Instant bef /// 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") Instant since, @Param("state") RideState state); + Long faresSince(@Param("since") long 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") Instant since); + List countByState(@Param("since") long 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") Instant since); + List countByProduct(@Param("since") long 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") Instant since, @Param("state") RideState state); + List countByDriver(@Param("since") long since, @Param("state") RideState state); /// One row for each ride asked for since `since`: `{id, requestedAt, /// state, fareCents, paymentStatus}`. @@ -334,7 +333,7 @@ List unsettled(@Param("after") Instant after, @Param("before") Instant bef /// 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") Instant since); + List timeline(@Param("since") long 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 5823d2f2173..5c4e79d5bf5 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,7 +44,6 @@ 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 @@ -181,9 +180,9 @@ public void seed(String[] riders, String[] drivers, boolean untilToday) throws I ride.setCurrency(fares.currency()); ride.setDistanceMeters(meters); ride.setDurationSeconds(seconds); - ride.setRequestedAt(Instant.ofEpochMilli(at)); - ride.setUpdatedAt(Instant.ofEpochMilli(ended)); - ride.setSearchUntil(Instant.ofEpochMilli(at + 90000L)); + ride.setRequestedAt(at); + ride.setUpdatedAt(ended); + ride.setSearchUntil(at + 90000L); ride.setStars(given); ride.setPaymentStatus(completed ? Payments.PAID : Payments.PENDING); ride.setProduct(products[driverIndex]); @@ -223,7 +222,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(Instant.ofEpochMilli(ended)); + payment.setCreatedAt(ended); paid.insert(payment); lastSeen[driverIndex] = Math.max(lastSeen[driverIndex], ended); if (ended < now - 7L * Days.MILLIS) { @@ -247,7 +246,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(Instant.ofEpochMilli(lastSeen[iter])); + car.setLastSeen(lastSeen[iter]); car.setRatingSum(stars[iter]); car.setRatingCount(rated[iter]); if (first) { @@ -266,7 +265,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(Instant.ofEpochMilli(now - 7L * Days.MILLIS)); + payout.setCreatedAt(now - 7L * Days.MILLIS); payout.setDestination("Bay Credit Union ****67" + (10 + iter)); payouts.insert(payout); } @@ -279,7 +278,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(Instant.ofEpochMilli(at)); + event.setCreatedAt(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 55275fbc8b2..b578c1a7f0e 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,7 +30,6 @@ import com.codenameone.examples.wayline.repository.PricingRepository; import java.io.IOException; -import java.time.Instant; /// What a ride costs. /// @@ -89,7 +88,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 || Instant.EPOCH.equals(row.getUpdatedAt())) { + if (row == null || row.getUpdatedAt() == 0L) { return defaults; } // The currency is a setting and stays one. Rides already taken are in @@ -122,7 +121,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(), Instant.now(), + wanted.comfortMultiplier(), wanted.xlMultiplier(), System.currentTimeMillis(), 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 a243eca7bca..4363ef2078f 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,7 +36,6 @@ 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; @@ -146,7 +145,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(Instant.now().minusMillis(FRESH_MILLIS), + List boxed = drivers.freeInBox(System.currentTimeMillis() - 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 52570aac5f6..8bc4db9443a 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,7 +53,6 @@ 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; @@ -235,7 +234,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); - Instant now = Instant.now(); + long now = System.currentTimeMillis(); // 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 @@ -256,7 +255,7 @@ private String open(String rider, RideRequestDto request) throws IOException { ride.setDurationSeconds(seconds); ride.setRequestedAt(now); ride.setUpdatedAt(now); - ride.setSearchUntil(now.plusMillis(searchMillis)); + ride.setSearchUntil(now + searchMillis); ride.setPaymentStatus(Payments.PENDING); ride.setProduct(product); ride.setMethodId(method[0]); @@ -413,9 +412,8 @@ 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 { - Instant now = Instant.now(); - List unsettled = unsettled(now.minusMillis(RETRY_MILLIS), - now.minusMillis(UNSETTLED_MILLIS)); + long now = System.currentTimeMillis(); + List unsettled = unsettled(now - RETRY_MILLIS, now - UNSETTLED_MILLIS); Exception failed = null; for (int iter = 0; iter < unsettled.size(); iter++) { Ride ride = unsettled.get(iter); @@ -436,7 +434,7 @@ public void settleLeftBehind() throws IOException { } @Transactional(readOnly = true) - private List unsettled(Instant after, Instant before) { + private List unsettled(long after, long before) { return rides.unsettled(after, before, new PageRequest(0, 50)); } @@ -570,12 +568,12 @@ private Change choose(String id, String[] chosen) throws IOException { if (ride == null || RideState.REQUESTED != ride.getState()) { return null; } - Instant now = Instant.now(); - if (now.isAfter(ride.getSearchUntil())) { + long now = System.currentTimeMillis(); + if (now > 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.toEpochMilli() - ride.getRequestedAt().toEpochMilli()); + chosen[0] = matcher.pick(ride, now - ride.getRequestedAt()); return null; } @@ -605,12 +603,11 @@ Change offer(String id, String driver) throws IOException { if (ride == null || RideState.REQUESTED != ride.getState()) { return null; } - Instant now = Instant.now(); - if (!matcher.fits(ride, driver, - now.toEpochMilli() - ride.getRequestedAt().toEpochMilli())) { + long now = System.currentTimeMillis(); + if (!matcher.fits(ride, driver, now - ride.getRequestedAt())) { return null; } - return tryMove(id, RideState.OFFERED, "", null, driver, now.plusMillis(offerMillis)) + return tryMove(id, RideState.OFFERED, "", null, driver, Long.valueOf(now + offerMillis)) ? new Change(id, RideState.OFFERED, ride.getRider(), driver, "", null) : null; } // end::wayline-ride-offer[] @@ -625,7 +622,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(Instant.now()); + List lapsed = lapsedOffers(System.currentTimeMillis()); for (int iter = 0; iter < lapsed.size(); iter++) { Ride ride = lapsed.get(iter); try { @@ -655,7 +652,7 @@ public void tick() throws IOException { } @Transactional(readOnly = true) - private List lapsedOffers(Instant now) throws IOException { + private List lapsedOffers(long now) throws IOException { return rides.findByStateAndOfferExpiresAtLessThan(RideState.OFFERED, now); } @@ -761,7 +758,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, - Instant newOfferExpiresAt) throws IOException { + Long newOfferExpiresAt) throws IOException { if (!tryMove(id, to, actor, ownerField, newDriver, newOfferExpiresAt)) { Ride now = find(id); throw new ResponseStatusException(409, "That ride is " @@ -784,15 +781,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, Instant newOfferExpiresAt) throws IOException { + String newDriver, Long newOfferExpiresAt) throws IOException { RideState[] sources = RideStateMachine.sources(to); if (sources.length == 0) { return false; } - Instant now = Instant.now(); + long now = System.currentTimeMillis(); int moved; if (newOfferExpiresAt != null) { - moved = rides.offer(id, sources, to, now, newDriver, newOfferExpiresAt); + moved = rides.offer(id, sources, to, now, newDriver, newOfferExpiresAt.longValue()); } else if (RIDER.equals(ownerField)) { moved = rides.moveAsRider(id, sources, to, now, actor); } else if (!DRIVER.equals(ownerField)) { @@ -820,7 +817,7 @@ private void event(String id, RideState state, String actor) throws IOException event.setRideId(id); event.setState(state); event.setActor(actor); - event.setCreatedAt(Instant.now()); + event.setCreatedAt(System.currentTimeMillis()); events.insert(event); } @@ -960,7 +957,7 @@ private RideDto toDto(Ride ride, String viewer, Map cache, bool } if (offered) { offerExpiresInSeconds = (int) Math.max(0L, - (ride.getOfferExpiresAt().toEpochMilli() - System.currentTimeMillis()) / 1000L); + (ride.getOfferExpiresAt() - System.currentTimeMillis()) / 1000L); } long fareCents = ride.getFareCents(); long serviceFee = ride.getFeeCents(); @@ -988,8 +985,8 @@ private RideDto toDto(Ride ride, String viewer, Map cache, bool ride.getCurrency(), ride.getDistanceMeters(), ride.getDurationSeconds(), - ride.getRequestedAt().toEpochMilli(), - ride.getUpdatedAt().toEpochMilli(), + ride.getRequestedAt(), + ride.getUpdatedAt(), ride.getStars(), ride.getPaymentStatus(), offerExpiresInSeconds, From c4fa4ca262130b73b04e5ad2c7ffde7cb49f81bb Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 24 Oct 2026 21:24:27 +0300 Subject: [PATCH 7/8] perf: raise the windows-x64 translator time row the nightly fold set too low Co-Authored-By: Claude Opus 5.5 --- vm/selfhost/perf-baseline/pr/6094.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/vm/selfhost/perf-baseline/pr/6094.json b/vm/selfhost/perf-baseline/pr/6094.json index 623efeb2297..1e54e2c016d 100644 --- a/vm/selfhost/perf-baseline/pr/6094.json +++ b/vm/selfhost/perf-baseline/pr/6094.json @@ -20,6 +20,26 @@ } } } + }, + "windows-x64@amd64-family-25-model-1-authenticamd": { + "translator": { + "all": { + "from": { + "memory": 0.542, + "time": 0.605, + "tolerance": { + "time": 0.35 + } + }, + "memory": 0.542, + "reason": "Translator all-cores time on this runner measures 0.83x (#6094) and 0.90x (#6098, no vm/ changes either) against a 0.60x row; the row is below the runner's normal spread", + "runs": 1, + "time": 0.833, + "tolerance": { + "time": 0.35 + } + } + } } } } From 0f1daaa993c50c3ab168a21efb0005a9994452dc Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Sat, 24 Oct 2026 23:47:40 +0300 Subject: [PATCH 8/8] perf: raise the second windows-x64 translator time row Co-Authored-By: Claude Opus 5.5 --- vm/selfhost/perf-baseline/pr/6094.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/vm/selfhost/perf-baseline/pr/6094.json b/vm/selfhost/perf-baseline/pr/6094.json index 1e54e2c016d..71539ff8303 100644 --- a/vm/selfhost/perf-baseline/pr/6094.json +++ b/vm/selfhost/perf-baseline/pr/6094.json @@ -40,6 +40,23 @@ } } } + }, + "windows-x64@amd64-family-25-model-17-authenticamd": { + "translator": { + "all": { + "from": { + "memory": 0.551, + "time": 0.701, + "tolerance": { + "time": 0.2 + } + }, + "memory": 0.551, + "reason": "Translator all-cores time on Windows x64 runners measures 0.83-0.90x on PRs with no vm/ changes (#6094, #6098) against rows the nightly fold set at 0.60-0.70x", + "runs": 1, + "time": 0.889 + } + } } } }