Emette la stringa della data ISO8601 da secondi e nanosecondi

Oct 20 2020

Uno dei motivi per cui ISO8601 è il miglior formato di stringa della data è che puoi semplicemente aggiungere la precisione che desideri. Dati 2 numeri interi che rappresentano secondi e nanosecondi trascorsi da allora 1970-01-01T00:00:00, restituisci una stringa ISO8601 come descritto di seguito.

Produzione:

Il formato di output standard senza fuso orario ha questo aspetto:

1970-01-01T00:00:00.000001

La data è codificata come "anno, mese, giorno" con 4,2,2 cifre rispettivamente, separate da un "-". L'ora del giorno è codificata come "ora, minuti, secondi" con 2,2,2 cifre rispettivamente. Quindi, facoltativamente, può seguire un punto con esattamente 6 cifre di precisione, che codifica i microsecondi trascorsi dopo la data specificata + (tempo in ore + minuti + secondi) da allora. Viene aggiunto solo se non è uguale a 000000. Vedere gli esempi di seguito

Sì, ci è permesso aggiungere 6 cifre (microsecondi) di precisione e teoricamente più sono semplicemente appendibili, sebbene non definite ulteriormente nello standard.

Ingresso:

Otterrai 2 numeri interi (secondi, nanosecondi). Per motivi di semplicità, costringiamoli a rientrare in 0 <= x < 10^9entrambi. Assicurati di scartare / arrotondare qualsiasi precisione oltre i microsecondi.

Esempi:

Input: 616166982 , 34699909     Output: 1989-07-11T13:29:42.034699
Input: 982773555 , 886139278    Output: 2001-02-21T16:39:15.886139
Input: 885454423 , 561869693    Output: 1998-01-22T07:33:43.561869
Input: 0         , 100000       Output: 1970-01-01T00:00:00.000100
Input: 0         , 1000         Output: 1970-01-01T00:00:00.000001
Input: 0         , 999          Output: 1970-01-01T00:00:00
Input: 999999999 , 999999999    Output: 2001-09-09T01:46:39.999999

Compito:

Fornire una funzione che accetta 2 numeri interi come descritto nella sezione Input e restituisce una stringa come descritto nella sezione Output.

Per dettagli e limitazioni per input / output, fare riferimento alle regole di input / output predefinite .

Questo è codegolf: vince la soluzione più breve in byte.

Risposte

5 NahuelFouilleul Oct 20 2020 at 01:10

Bash + sed, 37 , 59 , 50 byte

printf '%(%FT%T)T.%06d' $1 $[$2/1000]
printf "%(%FT%T)T.%06d" $1 ${2::-3}|sed s/\\.0*$//

Provalo online!

8 byte salvati grazie a @DigitalTrauma

3 att Oct 20 2020 at 04:28

Wolfram Language (Mathematica) , 91 byte

DateString[6!3068040+#2,"ISODateTime"]<>If[#>999,"."<>IntegerString[⌊#/1000⌋,10,6],""]&

Provalo online!

Mathematica supporta i millisecondi, ma non i microsecondi.

3 Noodle9 Oct 20 2020 at 05:54

C (gcc) , 108 106 byte

Risparmiato 2 byte grazie a Ceilingcat !!!

#import<time.h>
o[9];f(s,n)long s;{strftime(o,99,"%FT%T",gmtime(&s));printf((n/=1e3)?"%s.%06d":"%s",o,n);}

Provalo online!

Inserisce secondi e nanosecondi come numeri interi e restituisce la data / ora formattata a stdout.

3 NahuelFouilleul Oct 20 2020 at 01:43

Perl 5 ( -p -MPOSIX+strftime -Minteger), 55 , 51 , 60 byte

Grazie a @Abigail per avermi dato l'idea di cambiare il formato di input. + 9 byte per gestire i microsecondi = 0 case.

$_=(strftime"%FT%T",gmtime$_).sprintf".%06d",<>/1e3
$_=(strftime"%FT%T",gmtime$_).sprintf".%06d",<>/1e3;s;\.0+$;

Provalo online!

3 Shaggy Oct 20 2020 at 16:28

Japt , 32 28 byte

Accetta l'input come una coppia di stringhe, con i nanosecondi per primi. Può salvare (almeno) 4 byte se possiamo includere 0s iniziali con i nanosecondi.

ùT9 ¯6
pU=n g)iÐV*A³ s3 ¯UÄ9

Provalo

Oppure, per "tradurlo" in JavaScript:

U=>V=>(
    U=U.padStart(9,0).slice(0,6),
    U.repeat(U=Math.sign(parseInt(U))).replace(/^/,new Date(V*10**3).toISOString().slice(0,U+19))
)
ùT9 ¯6\npU=n g)iÐV*A³ s3 ¯UÄ9     :Implicit input of strings U=nanoseconds & V=seconds
ù                                 :Left pad U
 T                                :  With 0
  9                               :  To length 9
    ¯6                            :Slice to length 6
      \n                          :Reassign to U
        p                         :Repeat U
         U=                       :  Reassign to U
           n                      :  Convert to integer
             g                    :  Get sign
              )                   :End repeat
               i                  :Prepend
                Ð                 :  Create Date object from
                 V*               :    V multiplied by
                   A              :    10
                    ³             :    Cubed
                      s3          :  To ISO String
                         ¯U       :  Slice to length U
                           Ä9     :    +19
2 M.Justin Oct 20 2020 at 13:43

Groovy , 62 60 68 byte

f={s,n->"${java.time.Instant.ofEpochSecond(s,n|1)}"[0..25]-~/\.0+$/}

Provalo online!

Spiegazione

Il ofEpochSecond(epochSecond, nanoAdjustment)metodo Java restituisce il Instantcorrispondente ai secondi e ai nanosecondi dati (esattamente quello che vogliamo per questa sfida). I nanosecondi sono con OR bit per bit 1per garantire che non si finisca mai con esattamente 0 o 1_000_000 nanosecondi, pur mantenendo lo stesso comportamento di arrotondamento a 6 cifre.

"${...}"converte il Instantin a GStringcostituito dal Stringvalore dell'istante. La toStringrappresentazione di un Instantè in formato ISO-8601: "2011-12-03T10: 15: 30.000000001Z". Esclude automaticamente posizioni decimali extra oltre 0/3/6 cifre decimali (secondi / millisecondi / microsecondi) se le cifre rimanenti sono 0, quindi il precedente OR bit per bit.

"${value}"[0..25] restituisce i caratteri da 0 a 25 della stringa, che vanno dalla sesta cifra decimale.

-~/\.0+$/sottrae la prima istanza del pattern regex \.0+$dalla stringa risultante; vale a dire, una cifra decimale seguita da tutti zeri, seguita dalla fine della stringa. Ciò corrisponderà solo se la stringa termina con .000000e il codice è più corto di un carattere rispetto alla sottrazione '.000000'.

2 M.Justin Oct 23 2020 at 22:52

Groovy , 63 byte

f={s,n->sprintf('%tFT%1$tT.%06d',s*1000L,n/1E3as int)-~/\.0+$/}

Provalo online!

Un approccio Groovy diverso che utilizza stringhe di formato (ispirato ad altre risposte simili).

1 Adám Oct 20 2020 at 13:48

APL (Dyalog Unicode) 18.0, 53 byte ( SBCS )

Programma completo. Richiede nanosecondi, quindi secondi.

(¯7×0=f)↓⊃'%ISO%.ffffff'(1200⌶)20 1⎕DT⎕+1E¯6×f←⌊⎕÷1E3

Provalo online! (polyfills per ⌶e ⎕DTperché TIO usa ancora 17.1)

⎕÷1E3 dividere i nanosecondi di input per 1000

f← assegnato a f

1E¯6× moltiplicare per 0,000001

⎕+ aggiungere secondi di input a quello

20 1⎕DT convertire da UNIX time (secondi dal 1970) a Dyalog Date Number (giorni dal 1989-12-31)

'%ISO%.ffffff'(1200⌶) formato secondo ISO con precisione frazionaria a sei cifre

⊃ rivelare (perché una "stringa" è un vettore di caratteri racchiuso)

(... )↓ rilascia il seguente numero di caratteri

0=f uno se fè zero

¯7× sette dal retro in tal caso (lett. sette negativo moltiplicato per quello)

1 AZTECCO Oct 20 2020 at 04:13

JavaScript (V8) , 83 94 ... 78 byte

s=>n=>new Date(s*1e3).toJSON(n=0|n/1e3).slice(0,20-!n)+`${n+1e6}`.slice(n?1:7)

Provalo online!

  • Grazie a @Neil per il grande aiuto!
  • Ho salvato altri 5 grazie a @Arnauld
1 user0721090601 Oct 21 2020 at 03:49

Raku , 46 byte 40 caratteri, 42 byte

{(~DateTime.new($^a+$^b divⅯ/1e6)).chop}

Provalo online!

Salvati alcuni byte utilizzando un numero non numerico (che potrebbe essere sostituito da altri simili ൲, ma ad altri piace 𐄢o 𑁥aggiungono un byte in più), che consentiva la rimozione dello spazio dopo div. L'unico trucco qui era quello di forzare l'arrotondamento verso il basso e rafforzare il DateTimeper poterlo fare .chop. Potrebbe in effetti esserci un bug qui in quanto l'implementazione di Rakudo viene arrotondata, e se lo consideriamo tale, allora può essere ulteriormente considerato

{(~DateTime.new($^a+$^b/1e9)).chop}

Che sarebbero solo 35 caratteri / byte.

1 jaaq Oct 20 2020 at 00:02

Python 3.8 (pre-rilascio) 106 , 81 byte

lambda a,b:datetime.fromtimestamp(a+b//1e3/1e6).isoformat()
from datetime import*

Provalo online!

1 EngineerToast Oct 21 2020 at 03:36

Excel, 102101 byte

=TEXT(25569+A1/86400,"yyy-mm-ddThh:mm:ss")&SUBSTITUTE(LEFT(TEXT(B1/10^9,"."&REPT(0,9)),7),".000000",)

L'input è in secondi A1e in nanosecondi B1.

Ci sono due pezzi principali in questo:


TEXT(25569+A1/86400,"yyy-mm-ddThh:mm:ss")
25569è l'equivalente numerico di 1970-01-01 in Excel che misura da 1900-01-00 come zero.
A1/86400converte i secondi in giorni.
"yyyy-mm-ddThh:mm:ss"formatta il risultato, dandoci la maggior parte dell'output desiderato.


SUBSTITUTE(LEFT(TEXT(B1/10^9,"."&REPT(0,9)),7),".000000",)
TEXT(B1/10^9,"."&REPT(0,9))converte da un numero intero di nanosecondi a un decimale di secondi.
LEFT(TEXT(~),7)fornisce il punto decimale con le prime 6 cifre.
SUBSTITUTE(LEFT(~),".000000",)rappresenta un <1.000 nanosecondi facendo cadere il risultato.


A parte: dato quanto è amichevole Excel con le date, ha senso, ma è comunque fastidioso, che siano necessari più byte da gestire .000000di quanti ne richieda 1970-01-01T00:00:00. Ho trovato approcci alternativi con meno byte ma funzionano solo se possiamo arrotondare i nanosecondi o visualizzare valori zero. Ahimè e ahimè.