@Test public void testEntityBQTransform_toTableRow_timestamp() throws IOException { Entity e; EntityBQTransform strictEbt = EntityBQTransform.newBuilder() .setStrictCast(true) .setRowSchema(exampleTable().getFields()) .build(); EntityBQTransform nonstrictEbt = EntityBQTransform.newBuilder() .setStrictCast(false) .setRowSchema(exampleTable().getFields()) .build(); e = Entity.newBuilder() .putProperties("birthTimestamp", Value.newBuilder().setTimestampValue( Timestamp.newBuilder().setNanos(1000).setSeconds(1498692500).build()).build()) .build(); Assert.assertEquals("2017-06-28T23:28:20.000001Z", strictEbt.toTableRow(e).get("birthTimestamp")); Assert.assertEquals("2017-06-28T23:28:20.000001Z", nonstrictEbt.toTableRow(e).get("birthTimestamp")); }
@Test public void testEntityBQTransform_toTableRow_date() throws IOException { Entity e; EntityBQTransform strictEbt = EntityBQTransform.newBuilder() .setStrictCast(true) .setRowSchema(exampleTable().getFields()) .build(); EntityBQTransform nonstrictEbt = EntityBQTransform.newBuilder() .setStrictCast(false) .setRowSchema(exampleTable().getFields()) .build(); e = Entity.newBuilder() .putProperties("birthDate", Value.newBuilder().setTimestampValue( Timestamp.newBuilder().setNanos(1000).setSeconds(1498692500).build()).build()) .build(); Assert.assertEquals("2017-06-28", strictEbt.toTableRow(e).get("birthDate")); Assert.assertEquals("2017-06-28", nonstrictEbt.toTableRow(e).get("birthDate")); }
@Test public void testEntityBQTransform_toTableRow_time() throws IOException { Entity e; EntityBQTransform strictEbt = EntityBQTransform.newBuilder() .setStrictCast(true) .setRowSchema(exampleTable().getFields()) .build(); EntityBQTransform nonstrictEbt = EntityBQTransform.newBuilder() .setStrictCast(false) .setRowSchema(exampleTable().getFields()) .build(); e = Entity.newBuilder() .putProperties("birthTime", Value.newBuilder().setTimestampValue( Timestamp.newBuilder().setNanos(1000).setSeconds(1498692500).build()).build()) .build(); Assert.assertEquals("23:28:20.000001", strictEbt.toTableRow(e).get("birthTime")); Assert.assertEquals("23:28:20.000001", nonstrictEbt.toTableRow(e).get("birthTime")); }
@Test public void testEntityBQTransform_toTableRow_datetime() throws IOException { Entity e; EntityBQTransform strictEbt = EntityBQTransform.newBuilder() .setStrictCast(true) .setRowSchema(exampleTable().getFields()) .build(); EntityBQTransform nonstrictEbt = EntityBQTransform.newBuilder() .setStrictCast(false) .setRowSchema(exampleTable().getFields()) .build(); e = Entity.newBuilder() .putProperties("birthDateTime", Value.newBuilder().setTimestampValue( Timestamp.newBuilder().setNanos(1000).setSeconds(1498692500).build()).build()) .build(); Assert.assertEquals("2017-06-28 23:28:20.000001", strictEbt.toTableRow(e).get("birthDateTime")); Assert.assertEquals("2017-06-28 23:28:20.000001", nonstrictEbt.toTableRow(e).get("birthDateTime")); }
@Test public void testSingleClientRemoteSpan() { Span parent = Span.builder() .traceId(123L) .name("http:call") .begin(beginTime - 1) .end(endTime + 1) .log(new Log(beginTime, Span.CLIENT_SEND)) .log(new Log(endTime, Span.CLIENT_RECV)) .remote(true) .build(); this.spanListener.report(parent); Assert.assertEquals(1, this.test.traceSpans.size()); TraceSpan traceSpan = this.test.traceSpans.get(0); Assert.assertEquals("http:call", traceSpan.getName()); // Client span chould use CS and CR time, not Span begin or end time. Assert.assertEquals(Timestamp.getDefaultInstance(), traceSpan.getStartTime()); Assert.assertEquals(Timestamp.getDefaultInstance(), traceSpan.getEndTime()); Assert.assertEquals(this.dateFormatter.format(new Date(beginTime)), traceSpan.getLabelsOrThrow("cloud.spring.io/cs")); Assert.assertEquals(this.dateFormatter.format(new Date(endTime)), traceSpan.getLabelsOrThrow("cloud.spring.io/cr")); Assert.assertEquals(TraceSpan.SpanKind.RPC_CLIENT, traceSpan.getKind()); }
/** * Returns the {@link Operation} instance corresponding to this instance. * * @param clock is used to determine the current timestamp * * @return a {@link Operation} */ public Operation asOperation(Clock clock) { Operation.Builder b = Operation.newBuilder(); b.setImportance(Importance.LOW); Timestamp now = Timestamps.now(clock); b.setStartTime(now).setEndTime(now); if (!Strings.isNullOrEmpty(operationId)) { b.setOperationId(operationId); } if (!Strings.isNullOrEmpty(operationName)) { b.setOperationName(operationName); } String consumerId = getOperationConsumerId(); if (!Strings.isNullOrEmpty(consumerId)) { b.setConsumerId(consumerId); } return b.build(); }
@Test @DisplayName("set all the optional fields") void thirdCase() { final TaskCreationId pid = newPid(); final TaskId taskId = newTaskId(); testEnv.createDraft(pid, taskId); final String description = "thirdCase"; final TaskPriority priority = LOW; final Timestamp dueDate = add(getCurrentTime(), fromSeconds(100)); testEnv.setDetails(pid, description, priority, dueDate); final String labelTitle = "thirdCase-label"; final LabelId labelId = testEnv.createNewLabel(labelTitle); testEnv.addLabel(pid, labelId); testEnv.complete(pid); final Task task = testEnv.taskById(taskId); assertEquals(description, task.getDescription().getValue()); assertEquals(priority, task.getPriority()); assertAssignedLabel(taskId, labelTitle, GRAY); }
/** * Creates a new task with the given details fields. * * <p>Sends the {@link CreateBasicTask} command through the {@linkplain #client() gRPC client}. * * @param description the new task description */ void createTask(String description, TaskPriority priority, Timestamp taskDueDate) { final TaskDescription taskDescription = TaskDescription.newBuilder() .setValue(description) .build(); final SetTaskDetails command = SetTaskDetails.newBuilder() .setId(wizardId) .setDescription(taskDescription) .setPriority(priority) .setDueDate(taskDueDate) .build(); post(command); this.taskDescription = taskDescription; this.taskPriority = priority; this.taskDueDate = taskDueDate; }
private TaskItem getViewAfterUpdateTaskDueDate(Timestamp newDueDate, boolean isCorrectId) { final CreateDraft createDraft = createDraft(); client.postCommand(createDraft); final TaskId createdTaskId = createDraft.getId(); updateDueDate(newDueDate, isCorrectId, createdTaskId); final List<TaskItem> taskViews = client.getDraftTasksView() .getDraftTasks() .getItemsList(); assertEquals(1, taskViews.size()); final TaskItem view = taskViews.get(0); assertEquals(createdTaskId, view.getId()); return view; }
private TaskItem getViewAfterUpdateTaskDueDate(Timestamp newDueDate, boolean isCorrectId) { final CreateBasicTask createTask = createBasicTask(); client.postCommand(createTask); final TaskId idOfCreatedTask = createTask.getId(); updateDueDate(newDueDate, isCorrectId, idOfCreatedTask); final List<TaskItem> taskViews = client.getMyListView() .getMyList() .getItemsList(); assertEquals(1, taskViews.size()); final TaskItem view = taskViews.get(0); assertEquals(idOfCreatedTask, view.getId()); return view; }
/** * Creates commands setting the task details to the target task * * <p>This method is guaranteed to generate at least one command. Effectively, each non-default * field of the {@code SetTaskDetails} command causes a command to be generated. * * @param src the source command * @return new commands generated from the given {@code src} command */ Collection<? extends TodoCommand> setTaskDetails(SetTaskDetails src) { final ImmutableSet.Builder<TodoCommand> commands = ImmutableSet.builder(); final TaskDescription description = src.getDescription(); final TodoCommand updateDescription = updateTaskDescription(description); commands.add(updateDescription); final TaskPriority priority = src.getPriority(); if (enumIsNotDefault(priority)) { final TodoCommand updatePriority = updateTaskPriority(priority); commands.add(updatePriority); } final Timestamp dueDate = src.getDueDate(); if (isNotDefault(dueDate)) { final TodoCommand updateDueDate = updateTaskDueDate(dueDate); commands.add(updateDueDate); } return commands.build(); }
@Test @DisplayName("produce TaskDueDateUpdated event") void produceEvent() { final UpdateTaskDueDate updateTaskDueDateCmd = updateTaskDueDateInstance(taskId); final List<? extends Message> messageList = dispatchCommand(aggregate, envelopeOf(updateTaskDueDateCmd)); assertEquals(1, messageList.size()); assertEquals(TaskDueDateUpdated.class, messageList.get(0) .getClass()); final TaskDueDateUpdated taskDueDateUpdated = (TaskDueDateUpdated) messageList.get(0); assertEquals(taskId, taskDueDateUpdated.getTaskId()); final Timestamp newDueDate = taskDueDateUpdated.getDueDateChange() .getNewValue(); assertEquals(DUE_DATE, newDueDate); }
@Test @DisplayName("update the task due date in DraftTaskItem") void updateDueDate() { final TaskDraftCreated taskDraftCreatedEvent = taskDraftCreatedInstance(); dispatch(projection, createEvent(taskDraftCreatedEvent)); final Timestamp updatedDueDate = getCurrentTime(); final TaskId expectedTaskId = taskDraftCreatedEvent.getId(); final TaskDueDateUpdated taskDueDateUpdatedEvent = taskDueDateUpdatedInstance(expectedTaskId, updatedDueDate); dispatch(projection, createEvent(taskDueDateUpdatedEvent)); final TaskListView taskListView = projection.getState() .getDraftTasks(); assertEquals(1, taskListView.getItemsCount()); final TaskItem taskView = taskListView.getItemsList() .get(0); assertEquals(expectedTaskId, taskView.getId()); assertEquals(updatedDueDate, taskView.getDueDate()); }
@Test @DisplayName("not update the task due date by wrong task ID") void notUpdate() { taskDraftCreated(); final Timestamp updatedDueDate = getCurrentTime(); final TaskDueDateUpdated taskDueDateUpdatedEvent = taskDueDateUpdatedInstance(TaskId.getDefaultInstance(), updatedDueDate); dispatch(projection, createEvent(taskDueDateUpdatedEvent)); final TaskListView taskListView = projection.getState() .getDraftTasks(); assertEquals(1, taskListView.getItemsCount()); final TaskItem taskView = taskListView.getItemsList() .get(0); assertEquals(TASK_ID, taskView.getId()); assertNotEquals(updatedDueDate, taskView.getDueDate()); }
@Test @DisplayName("update the task due date on MyListView") void updateDueDate() { final TaskCreated taskCreatedEvent = taskCreatedInstance(); dispatch(projection, createEvent(taskCreatedEvent)); final Timestamp updatedDueDate = getCurrentTime(); final TaskId expectedTaskId = taskCreatedEvent.getId(); final TaskDueDateUpdated taskDueDateUpdatedEvent = taskDueDateUpdatedInstance(expectedTaskId, updatedDueDate); dispatch(projection, createEvent(taskDueDateUpdatedEvent)); final TaskListView taskListView = projection.getState() .getMyList(); assertEquals(1, taskListView.getItemsCount()); final TaskItem taskView = taskListView.getItemsList() .get(0); assertEquals(expectedTaskId, taskView.getId()); assertEquals(updatedDueDate, taskView.getDueDate()); }
@Test @DisplayName("not update the task due date in MyListView by wrong task ID") void doeNotUpdateDueDate() { final TaskCreated taskCreatedEvent = taskCreatedInstance(); dispatch(projection, createEvent(taskCreatedEvent)); final Timestamp updatedDueDate = getCurrentTime(); final TaskDueDateUpdated taskDueDateUpdatedEvent = taskDueDateUpdatedInstance(TaskId.getDefaultInstance(), updatedDueDate); dispatch(projection, createEvent(taskDueDateUpdatedEvent)); final TaskListView taskListView = projection.getState() .getMyList(); assertEquals(1, taskListView.getItemsCount()); final TaskItem taskView = taskListView.getItemsList() .get(0); assertNotEquals(updatedDueDate, taskView.getDueDate()); }
/** * createChannelHeader create chainHeader * * @param type header type. See {@link ChannelHeader.Builder#setType}. * @param txID transaction ID. See {@link ChannelHeader.Builder#setTxId}. * @param channelID channel ID. See {@link ChannelHeader.Builder#setChannelId}. * @param epoch the epoch in which this header was generated. See {@link ChannelHeader.Builder#setEpoch}. * @param timeStamp local time when the message was created. See {@link ChannelHeader.Builder#setTimestamp}. * @param chaincodeHeaderExtension extension to attach dependent on the header type. See {@link ChannelHeader.Builder#setExtension}. * @return a new chain header. */ public static ChannelHeader createChannelHeader(HeaderType type, String txID, String channelID, long epoch, Timestamp timeStamp, ChaincodeHeaderExtension chaincodeHeaderExtension) { if (isDebugLevel) { logger.debug(format("ChannelHeader: type: %s, version: 1, Txid: %s, channelId: %s, epoch %d", type.name(), txID, channelID, epoch)); } ChannelHeader.Builder ret = ChannelHeader.newBuilder() .setType(type.getNumber()) .setVersion(1) .setTxId(txID) .setChannelId(channelID) .setTimestamp(timeStamp) .setEpoch(epoch); if (null != chaincodeHeaderExtension) { ret.setExtension(chaincodeHeaderExtension.toByteString()); } return ret.build(); }
/** * Updates {@linkplain CommandContext.Schedule command schedule}. * * @param command a command to update * @param delay a {@linkplain CommandContext.Schedule#getDelay() delay} to set * @param schedulingTime the time when the command was scheduled by the {@code CommandScheduler} * @return an updated command */ static Command setSchedule(Command command, Duration delay, Timestamp schedulingTime) { checkNotNull(command); checkNotNull(delay); checkNotNull(schedulingTime); checkValid(schedulingTime); final CommandContext context = command.getContext(); final CommandContext.Schedule scheduleUpdated = context.getSchedule() .toBuilder() .setDelay(delay) .build(); final CommandContext contextUpdated = context.toBuilder() .setSchedule(scheduleUpdated) .build(); final Command.SystemProperties sysProps = command.getSystemProperties() .toBuilder() .setSchedulingTime(schedulingTime) .build(); final Command result = command.toBuilder() .setContext(contextUpdated) .setSystemProperties(sysProps) .build(); return result; }
@Test public void keep_multiple_filters_for_single_column() throws ParseException { final String columnName = "time"; final EntityColumn column = mock(EntityColumn.class); // Some valid Timestamp values final Timestamp startTime = Timestamps.parse("2000-01-01T10:00:00.000-05:00"); final Timestamp deadline = Timestamps.parse("2017-01-01T10:00:00.000-05:00"); final ColumnFilter startTimeFilter = gt(columnName, startTime); final ColumnFilter deadlineFilter = le(columnName, deadline); final Multimap<EntityColumn, ColumnFilter> columnFilters = ImmutableMultimap.<EntityColumn, ColumnFilter>builder() .put(column, startTimeFilter) .put(column, deadlineFilter) .build(); final CompositeQueryParameter parameter = from(columnFilters, ALL); final QueryParameters parameters = newBuilder().add(parameter) .build(); final List<CompositeQueryParameter> aggregatingParameters = newArrayList(parameters); assertSize(1, aggregatingParameters); final Multimap<EntityColumn, ColumnFilter> actualColumnFilters = aggregatingParameters.get(0).getFilters(); final Collection<ColumnFilter> timeFilters = actualColumnFilters.get(column); assertSize(2, timeFilters); assertContainsAll(timeFilters, startTimeFilter, deadlineFilter); }
@Test public void write_records_and_return_sorted_by_version_descending() { final int eventsNumber = 5; final List<AggregateEventRecord> records = newLinkedList(); final Timestamp timestamp = getCurrentTime(); Version currentVersion = zero(); for (int i = 0; i < eventsNumber; i++) { final Project state = Project.getDefaultInstance(); final Event event = eventFactory.createEvent(state, currentVersion, timestamp); final AggregateEventRecord record = StorageRecord.create(timestamp, event); records.add(record); currentVersion = increment(currentVersion); } writeAll(id, records); final Iterator<AggregateEventRecord> iterator = historyBackward(); final List<AggregateEventRecord> actual = newArrayList(iterator); reverse(records); // expected records should be in a reverse order assertEquals(records, actual); }
@Test public void sort_by_version_rather_then_by_timestamp() { final Project state = Project.getDefaultInstance(); final Version minVersion = zero(); final Version maxVersion = increment(minVersion); final Timestamp minTimestamp = Timestamps.MIN_VALUE; final Timestamp maxTimestamp = Timestamps.MAX_VALUE; // The first event is an event, which is the oldest, i.e. with the minimal version. final Event expectedFirst = eventFactory.createEvent(state, minVersion, maxTimestamp); final Event expectedSecond = eventFactory.createEvent(state, maxVersion, minTimestamp); storage.writeEvent(id, expectedSecond); storage.writeEvent(id, expectedFirst); final List<Event> events = storage.read(newReadRequest(id)) .get() .getEventList(); assertTrue(events.indexOf(expectedFirst) < events.indexOf(expectedSecond)); }
/** * Returns several records sorted by timestamp ascending. * * @param timestamp1 the timestamp of first record. */ public static List<AggregateEventRecord> sequenceFor(ProjectId id, Timestamp timestamp1) { final Duration delta = seconds(10); final Timestamp timestamp2 = add(timestamp1, delta); final Timestamp timestamp3 = add(timestamp2, delta); final TestEventFactory eventFactory = newInstance(Given.class); final Event e1 = eventFactory.createEvent(projectCreated(id, projectName(id)), null, timestamp1); final AggregateEventRecord record1 = StorageRecord.create(timestamp1, e1); final Event e2 = eventFactory.createEvent(taskAdded(id), null, timestamp2); final AggregateEventRecord record2 = StorageRecord.create(timestamp2, e2); final Event e3 = eventFactory.createEvent(EventMessage.projectStarted(id), null, timestamp3); final AggregateEventRecord record3 = StorageRecord.create(timestamp3, e3); return newArrayList(record1, record2, record3); }
@Test public void reschedule_commands_from_storage() { final Timestamp schedulingTime = minutesAgo(3); final Duration delayPrimary = Durations2.fromMinutes(5); final Duration newDelayExpected = Durations2.fromMinutes(2); // = 5 - 3 final List<Command> commandsPrimary = newArrayList(createProject(), addTask(), startProject()); storeAsScheduled(commandsPrimary, delayPrimary, schedulingTime); commandBus.rescheduleCommands(); final ArgumentCaptor<Command> commandCaptor = ArgumentCaptor.forClass(Command.class); verify(scheduler, times(commandsPrimary.size())).schedule(commandCaptor.capture()); final List<Command> commandsRescheduled = commandCaptor.getAllValues(); for (Command cmd : commandsRescheduled) { final long actualDelay = getDelaySeconds(cmd); Tests.assertSecondsEqual(newDelayExpected.getSeconds(), actualDelay, /*maxDiffSec=*/1); } }
@Test(expected = IllegalStateException.class) public void require_current_tenant_set() { final TenantAwareFunction0<Timestamp> whichTime = new TenantAwareFunction0<Timestamp>() { @Override public Timestamp apply() { return Time.getCurrentTime(); } }; // This should pass. new TenantAwareOperation(newUuid()) { @Override public void run() { whichTime.execute(); } }.execute(); // This should fail. whichTime.execute(); }
TraceSpan.Builder translate(TraceSpan.Builder spanBuilder, Span zipkinSpan) { spanBuilder.setName(zipkinSpan.name()); SpanKind kind = getSpanKind(zipkinSpan.kind()); spanBuilder.setKind(kind); rewriteIds(zipkinSpan, spanBuilder, kind); if (zipkinSpan.timestamp() != null) { spanBuilder.setStartTime(createTimestamp(zipkinSpan.timestamp())); if (zipkinSpan.duration() != null) { Timestamp endTime = createTimestamp(zipkinSpan.timestamp() + zipkinSpan.duration()); spanBuilder.setEndTime(endTime); } } spanBuilder.putAllLabels(labelExtractor.extract(zipkinSpan)); return spanBuilder; }
private Timestamp createTimestamp(long microseconds) { long seconds = (microseconds / 1000000); int remainderMicros = (int) (microseconds % 1000000); int remainderNanos = remainderMicros * 1000; return Timestamp.newBuilder().setSeconds(seconds).setNanos(remainderNanos).build(); }
@Override public void doMerge(JsonParser parser, int unused, Message.Builder messageBuilder) throws IOException { Timestamp.Builder builder = (Timestamp.Builder) messageBuilder; try { builder.mergeFrom(Timestamps.parse(ParseSupport.parseString(parser))); } catch (ParseException e) { throw new InvalidProtocolBufferException( "Failed to readValue timestamp: " + parser.getText()); } }
@Override public void getTime(Empty request, StreamObserver<TimeReply> responseObserver) { // JDK8 type Instant now = Instant.now(); logger.info("Reporting the time " + now); // Protobuf type Timestamp protoNow = MoreTimestamps.fromInstantUtc(now); TimeReply reply = TimeReply.newBuilder().setTime(protoNow).build(); // Respond responseObserver.onNext(reply); responseObserver.onCompleted(); }
public static Timestamp fromInstantUtc(@Nonnull Instant instant) { checkNotNull(instant, "instant"); return Timestamp.newBuilder() .setSeconds(instant.getEpochSecond()) .setNanos(instant.getNano()) .build(); }
@Override public void merge(JsonElement json, Builder builder) throws InvalidProtocolBufferException { try { Timestamp value = Timestamps.parse(json.getAsString()); builder.mergeFrom(value.toByteString()); } catch (ParseException e) { throw new InvalidProtocolBufferException("Failed to parse timestamp: " + json); } }
private void mergeTimestamp(JsonElement json, Message.Builder builder) throws InvalidProtocolBufferException { try { Timestamp value = Timestamps.parse(json.getAsString()); builder.mergeFrom(value.toByteString()); } catch (ParseException e) { throw new InvalidProtocolBufferException("Failed to parse timestamp: " + json); } }
protected Timestamp createTimestamp(long milliseconds) { long seconds = (milliseconds / 1000); int remainderMicros = (int) (milliseconds % 1000); int remainderNanos = remainderMicros * 1000000; return Timestamp.newBuilder().setSeconds(seconds).setNanos(remainderNanos).build(); }
@Test public void testSingleServerRemoteSpan() { Span parent = Span.builder() .traceId(123L) .name("http:parent") .begin(beginTime - 1) .end(endTime + 1) .log(new Log(beginTime, Span.SERVER_RECV)) .log(new Log(endTime, Span.SERVER_SEND)) .remote(true) .build(); this.spanListener.report(parent); Assert.assertEquals(1, this.test.traceSpans.size()); TraceSpan traceSpan = this.test.traceSpans.get(0); Assert.assertEquals(0, traceSpan.getParentSpanId()); Assert.assertEquals("http:parent", traceSpan.getName()); // Server side remote span should not report start/end time Assert.assertEquals(Timestamp.getDefaultInstance(), traceSpan.getStartTime()); Assert.assertEquals(Timestamp.getDefaultInstance(), traceSpan.getEndTime()); Assert.assertEquals(this.dateFormatter.format(new Date(beginTime)), traceSpan.getLabelsOrThrow("cloud.spring.io/sr")); Assert.assertEquals(this.dateFormatter.format(new Date(endTime)), traceSpan.getLabelsOrThrow("cloud.spring.io/ss")); Assert.assertEquals(TraceSpan.SpanKind.RPC_SERVER, traceSpan.getKind()); }
public static ZonedDateTime timestampToZonedDateTime(Timestamp timestamp) { return timestamp == null ? null : ZonedDateTime.ofInstant( Instant.ofEpochSecond( timestamp.getSeconds(), timestamp.getNanos()), ZoneId.of("UTC") ); }
@Override public int compare(Timestamp o1, Timestamp o2) { int secondsOrder = Long.compare(o1.getSeconds(), o2.getSeconds()); if (secondsOrder != 0) { return secondsOrder; } else { return Long.compare(o1.getNanos(), o2.getNanos()); } }
/** * Obtain the current time from the unix epoch * * @param epochMillis gives the current time in milliseconds since since the epoch * @return a {@code Timestamp} corresponding to the ticker's current value */ public static Timestamp fromEpoch(long epochMillis) { return Timestamp .newBuilder() .setNanos((int) ((epochMillis % MILLIS_PER_SECOND) * NANOS_PER_MILLI)) .setSeconds(epochMillis / MILLIS_PER_SECOND) .build(); }