Skip to content

Commit

Permalink
Add support for timezoned timestamp to metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
pditommaso committed Aug 6, 2019
1 parent 2e0f5c2 commit 6f4a2e2
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 21 deletions.
Expand Up @@ -18,6 +18,7 @@ package nextflow.script

import java.nio.file.Path
import java.nio.file.Paths
import java.time.OffsetDateTime

import groovy.transform.CompileStatic
import groovy.transform.PackageScope
Expand Down Expand Up @@ -78,13 +79,17 @@ class WorkflowMetadata {

/**
* Timestamp at workflow execution start
*
* Use OffDateTime instead of Date -- See https://stackoverflow.com/a/32443004/395921
*/
Date start
OffsetDateTime start

/**
* Timestamp at workflow execution complete
*
* Use OffDateTime instead of Date -- See https://stackoverflow.com/a/32443004/395921
*/
Date complete
OffsetDateTime complete

/**
* Time elapsed to complete workflow execution
Expand Down Expand Up @@ -217,7 +222,8 @@ class WorkflowMetadata {
this.commitId = scriptFile?.commitId
this.revision = scriptFile?.revision
this.projectDir = scriptFile?.localPath
this.start = new Date()
this.projectName = scriptFile?.projectName ?: scriptName
this.start = OffsetDateTime.now()
this.container = session.fetchContainers()
this.commandLine = session.commandLine
this.nextflow = NextflowMeta.instance
Expand Down Expand Up @@ -364,8 +370,8 @@ class WorkflowMetadata {
*/
@PackageScope
void invokeOnComplete() {
this.complete = new Date()
this.duration = Duration.of( complete.time - start.time )
this.complete = OffsetDateTime.now()
this.duration = Duration.between( start, complete )
this.success = !(session.aborted || session.cancelled)

setErrorAttributes()
Expand Down
Expand Up @@ -137,7 +137,7 @@ <h4>Workflow execution completed unsuccessfully!</h4>
<dl>
<dt>Run times</dt>
<dd>
<span id="workflow_start">${workflow.start}</span> - <span id="workflow_complete">${workflow.complete}</span>
<span id="workflow_start">${workflow.start.format('dd-MMM-yyyy HH:mm:ss')}</span> - <span id="workflow_complete">${workflow.complete.format('dd-MMM-yyyy HH:mm:ss')}</span>
(<span id="completed_fromnow"></span>duration: <strong>${workflow.duration}</strong>)
</dd>

Expand Down
Expand Up @@ -30,7 +30,7 @@ class NextflowMetaTest extends Specification {
map.version == '10.12.0'
map.build == 123
map.preview.dsl == 2
dateToString(map.timestamp) == Const.APP_TIMESTAMP_UTC
dateToString((Date)map.timestamp) == Const.APP_TIMESTAMP_UTC

}
}
Expand Up @@ -16,10 +16,9 @@

package nextflow.script

import spock.lang.Specification

import java.nio.file.Files
import java.nio.file.Paths
import java.time.OffsetDateTime

import nextflow.Const
import nextflow.Session
Expand All @@ -28,8 +27,8 @@ import nextflow.trace.TraceRecord
import nextflow.util.Duration
import nextflow.util.VersionNumber
import org.eclipse.jgit.api.Git
import spock.lang.Specification
import test.TestHelper

/**
*
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Expand All @@ -39,7 +38,7 @@ class WorkflowMetadataTest extends Specification {
def 'should populate workflow object' () {

given:
final begin = new Date()
final begin = OffsetDateTime.now()
def dir = Files.createTempDirectory('test')
/*
* create the github repository
Expand Down Expand Up @@ -99,7 +98,7 @@ class WorkflowMetadataTest extends Specification {
metadata.projectDir == dir
metadata.projectName == 'nextflow-io/rnaseq-nf'
metadata.start >= begin
metadata.start <= new Date()
metadata.start <= OffsetDateTime.now()
metadata.complete == null
metadata.commandLine == 'nextflow run -this -that'
metadata.nextflow.version == new VersionNumber(Const.APP_VER)
Expand All @@ -120,8 +119,8 @@ class WorkflowMetadataTest extends Specification {
metadata.invokeOnComplete()
then:
metadata.complete > metadata.start
metadata.complete <= new Date()
metadata.duration == new Duration( metadata.complete.time - metadata.start.time )
metadata.complete <= OffsetDateTime.now()
metadata.duration == Duration.between(metadata.start, metadata.complete)
handlerInvoked == metadata.commandLine


Expand Down
Expand Up @@ -17,6 +17,9 @@
package nextflow.script

import java.nio.file.Paths
import java.time.Instant
import java.time.OffsetDateTime
import java.time.ZoneId

import nextflow.NextflowMeta
import nextflow.mail.Attachment
Expand All @@ -38,14 +41,14 @@ class WorkflowNotifierTest extends Specification {
given:
def work = TestHelper.createInMemTempDir()
def sessionId = UUID.randomUUID()
def now = new Date(1513285947928)
def end = new Date( now.time + 150_000 )
def now = OffsetDateTime.ofInstant(Instant.ofEpochMilli(1513285947928), ZoneId.systemDefault())
def end = now.plusSeconds(150)
def meta = new WorkflowMetadata(
runName: 'foo_bartali',
exitStatus: 0,
start: now,
complete: end,
duration: Duration.of( end.time - now.time ),
duration: Duration.between( now, end ),
commandLine: 'nextflow run big-workflow',
launchDir: Paths.get('/launch/dir'),
workDir: work,
Expand Down Expand Up @@ -163,16 +166,16 @@ class WorkflowNotifierTest extends Specification {

given:
def sessionId = UUID.randomUUID()
def now = new Date(1513285947928)
def end = new Date( now.time + 150_000 )
def now = OffsetDateTime.ofInstant(Instant.ofEpochMilli(1513285947928), ZoneId.systemDefault())
def end = now.plusSeconds(150)
def workDir = TestHelper.createInMemTempDir()

def meta = new WorkflowMetadata(
runName: 'foo_bartali',
exitStatus: 0,
start: now,
complete: end,
duration: Duration.of( end.time - now.time ),
duration: Duration.between( now, end ),
commandLine: 'nextflow run big-workflow',
launchDir: Paths.get('/launch/dir'),
workDir: workDir,
Expand Down
Expand Up @@ -15,9 +15,10 @@
*/

package nextflow.trace

import java.nio.file.Files
import java.nio.file.Paths
import java.util.concurrent.Executors
import java.time.OffsetDateTime

import groovy.json.JsonSlurper
import nextflow.NextflowMeta
Expand Down Expand Up @@ -115,6 +116,8 @@ class ReportObserverTest extends Specification {
given:
def workDir = TestHelper.createInMemTempDir()
def workflow = new WorkflowMetadata(
start: OffsetDateTime.now(),
complete: OffsetDateTime.now(),
workDir: workDir,
stats: new WorkflowStats(),
nextflow: new NextflowMeta('0.27.9', 3232, '2017-12-12')
Expand Down
6 changes: 6 additions & 0 deletions modules/nf-commons/src/main/nextflow/extension/Bolts.groovy
Expand Up @@ -20,6 +20,8 @@ import java.nio.file.NoSuchFileException
import java.nio.file.Path
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
import java.util.concurrent.locks.Lock
import java.util.regex.Pattern

Expand Down Expand Up @@ -83,6 +85,10 @@ class Bolts {
getLocalDateFormat(format ?: DATETIME_FORMAT, zone).get().format(self)
}

static String format(OffsetDateTime self, String format) {
return self.format(DateTimeFormatter.ofPattern(format))
}

/**
* Format a {@link Date} object
*
Expand Down
5 changes: 5 additions & 0 deletions modules/nf-commons/src/main/nextflow/util/Duration.groovy
Expand Up @@ -16,6 +16,7 @@

package nextflow.util

import java.time.temporal.Temporal
import java.util.concurrent.TimeUnit

import groovy.transform.CompileStatic
Expand Down Expand Up @@ -210,6 +211,10 @@ class Duration implements Comparable<Duration>, Serializable, Cloneable {
}
}

static Duration between( Temporal start, Temporal end ) {
new Duration(java.time.Duration.between(start, end).toMillis())
}

long toMillis() {
durationInMillis
}
Expand Down
17 changes: 17 additions & 0 deletions modules/nf-commons/src/test/nextflow/extension/BoltsTest.groovy
Expand Up @@ -16,6 +16,10 @@

package nextflow.extension

import java.time.Instant
import java.time.OffsetDateTime
import java.time.ZoneId

import spock.lang.Specification
import spock.lang.Unroll

Expand Down Expand Up @@ -54,6 +58,19 @@ class BoltsTest extends Specification {

}

def 'should format offset datetime' () {
given:
def now = OffsetDateTime.ofInstant(Instant.ofEpochMilli(1513285947928), ZoneId.of('CET'))
expect:
now.format(FMT) == EXPECTED

where:
FMT | EXPECTED
'dd-MM-yyyy HH:mm' | '14-12-2017 22:12'
'dd-MMM-yyyy HH:mm:ss' | '14-Dec-2017 22:12:27'

}

def testTrimDotZero() {

expect:
Expand Down
13 changes: 13 additions & 0 deletions modules/nf-commons/src/test/nextflow/util/DurationTest.groovy
Expand Up @@ -16,6 +16,8 @@

package nextflow.util

import java.time.Instant

import spock.lang.Specification

/**
Expand Down Expand Up @@ -181,4 +183,15 @@ class DurationTest extends Specification {
}


def 'should validate duration between' () {

given:
def start = Instant.now()
def end = start.plusMillis(1000)

expect:
Duration.between(start, end) == Duration.of('1sec')
}


}

0 comments on commit 6f4a2e2

Please sign in to comment.