Un año fraccional

8

Mis vacaciones PPCG terminaron: D

Introducción

El tiempo fraccional es the year + (the value (minute of year) / number of minutes in the year).

Ejemplo de cálculo

Debe suponer que febrero siempre tiene 28 días y que el año siempre tiene 365 días.

Digamos que queremos convertir el tiempo: 17:34 3rd March 2013en tiempo fraccionario. En primer lugar, encuentra cuántos minutos había en 2013: 525600 minutos . Llamemos esto x.

A continuación, desea averiguar cuántos minutos han pasado desde principios de 2013. Algunos cálculos rápidos le indicarán que la respuesta es 88894 minutos:

Han pasado 61 días desde el comienzo del año, que multiplicado por 1440 (número de minutos en un día) equivale a 87840 minutos. En 17 horas son 1020 minutos (17 * 60). Ahora, podemos agregar 87840, 1020 y 34 minutos para igualar 88894 minutos.

Llamemos esto y.

Finalmente, divides ypor xy sumas el año, resultando en 2013.16912(hasta 5 decimales).

Entrada

La fecha y la hora se darán como una sola cadena. La cadena tendrá el siguiente formato:

YYYY-MM-DD hh:mm 

El tiempo siempre estará en formato de 24 horas y el año siempre estará en el rango 1900-2050 inclusive.

Ejemplos

Input:  2016-08-06 23:48
Output: 2016.59723

Input:  2013-03-03 17:34
Output: 2013.16912

Input:  1914-11-11 11:11
Output: 1914.86155

Si va por la recompensa, hágame ping en los comentarios o en The Nineteenth Byte .

Desafío

Calcule la fecha y hora dadas como un año fraccionario.

Dé toda la salida a cinco decimales (puede redondear de la forma que desee: piso, techo o redondeo verdadero). El código más corto gana.

Generosidad

Estoy ofreciendo una recompensa de 100 repeticiones por el programa más corto que también acepta la fecha en formato de año fraccionario y devuelve la hora en YYYY-MM-DD hh:mmformato. En esencia, su programa (o función) tiene que actuar de la siguiente manera:

f('1914-11-11 11:11') => 1914.86155
f('1914.86155')       => 1914-11-11 11:11
  1. t-clausen.dk - 154 bytes
  2. Neil - 183 bytes

Tabla de clasificación

Decaimiento Beta
fuente
¿Quizás tomar la fecha y la hora como entrada permitiría casos de prueba y una verificación más fácil?
Luis Mendo
Estoy un poco confundido sobre si esto tiene en cuenta los años bisiestos dados For this, assume February has 28 days and the year is 365 days long., pero también... using the Gregorian calendar.
Destructible Lemon
@DestructibleWatermelon No, no tiene en cuenta los años bisiestos
Beta Decay
¿podemos dar más de cinco decimales?
Destructible Lemon
@DestructibleWatermelon No
Decaimiento Beta

Respuestas:

1

TSQL, 63 bytes

Esta es una versión más corta que mi respuesta original, porque mi primera respuesta incluía el cálculo para el año bisiesto.

DECLARE @ DATETIME ='2016-08-06 23:48'

PRINT LEFT(YEAR(@)+DATEDIFF(mi,0,STUFF(@,1,4,1900))/525600.,10)

Violín

El siguiente sql puede manejar ambos tipos de entrada

TSQL, 154 bytes

DECLARE @ VARCHAR(16) ='1914-11-11 11:11'--can be replaced with '1914.86155'

PRINT IIF(isdate(@)=1,LEFT(YEAR(@)+DATEDIFF(mi,0,STUFF(@,1,4,1900))/525600.,10),LEFT(@,4)+RIGHT(CONVERT(CHAR(16),DATEADD(mi,1*RIGHT(@,5)*5.256,0),20),12))

Violín combinado 1

Violín combinado 2

t-clausen.dk
fuente
5

JavaScript (ES6), 84 bytes

f=
s=>(Date.parse(1970+s.slice(4).replace(/ /,'T')+'Z')/31536e6+parseInt(s)).toFixed(5)
;
<input placeholder=Input oninput=o.value=f(this.value)><input placeholder=Output id=o>

Suponiendo que no se requieren años bisiestos o DST, reemplazo el año con 1970, lo que hace Date.parseque devuelva directamente la compensación de tiempo en milisegundos, que hubo 31536000000en 1970 (o de hecho, cualquier otro año no bisiesto). Todo lo que necesito hacer es volver a agregar el año y redondear a 5 decimales. Editar: conversión bidireccional en 183 178 bytes:

f=
s=>/:/.test(s,m=31536e6)?(Date.parse(1970+s.slice(4).replace(/ /,'T')+'Z')/m+parseInt(s)).toFixed(5):s.slice(0,4)+new Date(s.slice(4)*m+3e4).toJSON().slice(4,16).replace(/T/,' ')
;
<input placeholder=Input oninput=o.value=f(this.value)><input placeholder=Output id=o>

Asume que las cadenas que contienen un :formato de hora se manejan como se indica arriba, de lo contrario se quita el año, se convierte a milisegundos, se agrega medio minuto para redondear, se convierte a una fecha en 1970, se extrae el mes, el día, la hora y los minutos, y se prefieren los año original

Neil
fuente
@ βετѧΛєҫαγ Sí, ses el argumento de la función.
Neil
¿No da esto una salida inválida, porque el desafío pide explícitamente que febrero solo tenga 28 días y 365 días por año en total?
AdmBorkBork
@TimmyD a veces febrero tiene 29 días. Supongamos que no significa que no está permitido manejar correctamente los años bisiestos
t-clausen.dk
@ t-clausen.dk Lo siento, quise decir que los años bisiestos no deberían ser manejados
Beta Decay
@ βετѧΛєҫαγ Ahora no utiliza ni años bisiestos ni horario de verano, y también tiene una versión reversible. ¿Es eso satisfactorio?
Neil
2

Matlab, 132115 bytes

 d=input('');m=cumsum([-1 '# #"#"##"#"'-4]);year(d)+fix((((m(month(d))+day(d))*24+hour(d))*60+minute(d))/5.256)/10^5

Redondea hacia 0.

Hmmm ... eso es bastante largo.
Eso está usando algunos componentes incorporados, pero no los realmente útiles, debido a los años bisiestos.

Analizar la cadena directamente da 2 bytes más de solución:

d=sscanf(input(''),'%d%[- :]');m=cumsum([-1 '# #"#"##"#"'-4]);d(1)+fix((((m(d(3))+d(5))*24+d(7))*60+d(9))/5.256)/10^5

Las versiones más recientes de Matlab probablemente tengan una mejor función de división, pero estoy ejecutando en 2012a.

Algunos bytes guardados gracias a @Luis Mendo

pajonk
fuente
Puede definir la matriz con [-1 '# #"#"##"#"'-4]para guardar algunos bytes. ¿Son yearlas funciones estándar etc.? Si está utilizando una caja de herramientas, debe indicarla en el título, por ejemplo, "Matlab with Financial Toolbox"
Luis Mendo
@LuisMendo No estoy familiarizado con la #notación y nunca la encontré. ¿Dónde puedo leer más al respecto (la búsqueda rápida en Google no ayudó)? Creo que yearetc. son funciones estándar, pero no sé si se comportan igual fuera de la caja de herramientas (docs) .
pajonk
No es una notación especial. Es solo una cadena con caracteres que tienen los códigos ASCII apropiados para producir los números requeridos. En cuanto a las funciones, no lo sabía, gracias por aclarar. Matlab 15b no parece tenerlos
Luis Mendo
Oh, eso es inteligente.
pajonk
1

PowerShell v3 +, 131 bytes

$t=date $args[0];$a=1440*!!(date "2-29-$($t.year)");"{0:F5}"-f((($t.DayOfYear-1)*1440+$t.TimeOfDay.TotalMinutes-$a)/525600+$t.Year)

Toma información $args[0]y la convierte Get-Datepara almacenar en [datetime]formato .NET , almacena en $t. Calcula si existe el 29 de febrero y establece, $apor lo que restamos el valor de minutos de esa fecha (si está presente).

Luego usamos el -foperador ormat con una especificación de cadena fija de 5 dígitos decimales para ejecutar el cálculo. Utiliza funciones integradas para calcular el .DayOfYeary el .TotalMinutesde la entrada dada, restar $asi es un año bisiesto, dividir por 525600minutos en total y agregar la entrada .Year.

Se quejará (verbosamente) a STDERR si el 29 de febrero no existe (ver ejemplos a continuación), pero dado que STDERR es ignorado por defecto, no nos preocupamos por eso. Además, tenga en cuenta que PowerShell realiza el redondeo bancario por defecto.

Ejemplos

PS C:\Tools\Scripts\golfing> .\fractional-year.ps1 '2016-08-06 23:48'
2016.59724

PS C:\Tools\Scripts\golfing> .\fractional-year.ps1 '2013-03-03 17:34'
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "2-29-2013" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At C:\Tools\Scripts\golfing\fractional-year.ps1:7 char:36
+   $t=date $args[0];$a=1440*!!(date "2-29-$($t.year)");"{0:F5}"-f((($t.DayOfYear- ...
+                                    ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Date], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand

2013.16913

PS C:\Tools\Scripts\golfing> .\fractional-year.ps1 '1914-11-11 11:11'
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "2-29-1914" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At C:\Tools\Scripts\golfing\fractional-year.ps1:7 char:36
+   $t=date $args[0];$a=1440*!!(date "2-29-$($t.year)");"{0:F5}"-f((($t.DayOfYear- ...
+                                    ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Date], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand

1914.86155

Alternativamente, con años bisiestos, 119 bytes

"{0:F5}"-f((($t=date $args[0]).DayOfYear-1+$t.TimeOfDay.TotalMinutes/1440)/(date "12-31-$($t.year)").DayOfYear+$t.Year)

Si seguimos la configuración del calendario, podemos reducir una docena de bytes porque no necesitaremos tener en cuenta $aen el código original anterior. Esto nos permite pasar $ta la expresión en sí, y calcularemos explícitamente el .DayOfYear31 de diciembre. De lo contrario, sigue la misma metodología.

AdmBorkBork
fuente
0

Python 3, 163 173 bytes

más bytes debido al formato de salida

no utiliza ninguna fecha incorporada, como la respuesta de Java.

def s(x):z=x[5:10].split("-");v=x[10:].split(":");return int(x[:4])+(sum(([-1,31,28]+[31,30,31,30,31]*2)[:int(z[0])],int(z[1]))*1440+int(v[0])*60+int(v[1]))/525600

un poco más legible

def s(x):
    date=x[5:10].split("-");time=x[10:].split(":")
    return int(x[:4])+(sum(([-1,31,28]+[31,30,31,30,31]*2)[:int(date[0])],int(date[1]))*1440+int(time[0])*60+int(time[1]))/525600
Limón Destructible
fuente
0

Perl 6 ,  107105102  bytes

{$/=.comb(/\d+/);($0+(sum(|flat(-1,31,28,(31,30,31,30,31)xx 2)[^$1],$2)*1440+$3*60+$4)/525600).fmt: '%.5f'}
{$/=.comb(/\d+/);fmt $0+(sum(|flat(-1,31,28,(31,30,31,30,31)xx 2)[^$1],$2)*1440+$3*60+$4)/525600: '%.5f'}

{$/=.comb(/\d+/);fmt $0+(flat($2-1,31,28,(31,30,31,30,31)xx 2)[^$1].sum*1440+$3*60+$4)/525600: '%.5f'}
{$/=.comb(/\d+/);round $0+(flat($2-1,31,28,(31,30,31,30,31)xx 2)[^$1].sum*1440+$3*60+$4)/525600,.1⁵}

Explicación:

{
  $/ = .comb(/\d+/); # grab a list of only the digits
  # 「$0」 is short for 「$/[0]」

  fmt

    $0 # year
    +
    (
      flat(
        $2 -1,                     #    days
        31,28,(31,30,31,30,31)xx 2 # -+ months
      )[^$1].sum * 1440            # /
      + $3 * 60                    #    hours
      + $4                         #    minutes
    )
    /
    525600

  : '%.5f' # the 「:」 is used here as 「fmt」 is a method not a subroutine
}

Prueba:

#! /usr/bin/env perl6
use v6.c;
use Test;

# returns Str
my &fractional-year-a = {$/=.comb(/\d+/);fmt $0+(sum(flat($2-1,31,28,(31,30,31,30,31)xx 2)[^$1])*1440+$3*60+$4)/525600: '%.5f'}
# returns Rat
my &fractional-year-b = {$/=.comb(/\d+/);round $0+(sum(flat($2-1,31,28,(31,30,31,30,31)xx 2)[^$1])*1440+$3*60+$4)/525600,.1⁵}

my @tests = (
  '2016-08-06 23:48' => 2016.59723,
  '2013-03-03 17:34' => 2013.16912,
  '1914-11-11 11:11' => 1914.86155,
);

plan +@tests * 2;

for @tests -> $_ ( :key($input), :value($expected) ) {
  is-approx +fractional-year-a($input), +$expected, 1e-5, "a $input => $expected";
  is-approx +fractional-year-b($input), +$expected, 1e-5, "b $input => $expected";
}
1..6
ok 1 - a 2016-08-06 23:48 => 2016.59723
ok 2 - b 2016-08-06 23:48 => 2016.59723
ok 3 - a 2013-03-03 17:34 => 2013.16912
ok 4 - b 2013-03-03 17:34 => 2013.16912
ok 5 - a 1914-11-11 11:11 => 1914.86155
ok 6 - b 1914-11-11 11:11 => 1914.86155
Brad Gilbert b2gills
fuente