Tahun Pecahan

8

Liburan PPCG saya selesai: D

Intro

Waktu pecahan adalah the year + (the value (minute of year) / number of minutes in the year).

Contoh perhitungan

Anda harus berasumsi bahwa Februari selalu memiliki 28 hari dan tahun selalu 365 hari.

Katakanlah kita ingin mengubah waktu: 17:34 3rd March 2013ke waktu fraksional. Pertama, Anda menemukan berapa menit pada 2013: 525600 menit . Sebut ini x.

Selanjutnya, Anda ingin mengetahui berapa menit yang sudah ada sejak awal 2013. Beberapa perhitungan cepat akan memberi tahu Anda bahwa jawabannya adalah 88894 menit:

Sudah ada 61 hari sejak awal tahun, yang kali 1440 (jumlah menit dalam sehari) sama dengan 87.840 menit. Dalam 17 jam adalah 1020 menit (17 * 60). Sekarang, kita dapat menambahkan 87.840, 1020 dan 34 menit menjadi sama dengan 88.894 menit.

Sebut ini y.

Akhirnya, Anda membagi ydengan xdan menambahkan tahun, menghasilkan 2013.16912(ke 5 tempat desimal).

Memasukkan

Tanggal dan waktu akan diberikan sebagai string tunggal. String akan berada dalam format berikut:

YYYY-MM-DD hh:mm 

Waktu akan selalu dalam format 24 jam dan tahun akan selalu berada dalam kisaran 1900-2050 inklusif.

Contohnya

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

Jika Anda mencari hadiahnya, ping saya di komentar atau di The Nineteenth Byte .

Tantangan

Hitung tanggal dan waktu yang diberikan sebagai tahun pecahan.

Berikan semua output ke lima tempat desimal (Anda dapat membulatkannya sesuai keinginan: lantai, langit-langit, atau pembulatan sejati). Kode terpendek menang.

Karunia

Saya menawarkan hadiah 100 rep untuk program terpendek yang juga menerima tanggal dalam format tahun pecahan dan mengembalikan waktu dalam YYYY-MM-DD hh:mmformat. Intinya, program Anda (atau fungsi) harus bertindak dengan cara berikut:

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

Papan peringkat

Peluruhan Beta
sumber
Mungkin mengambil tanggal dan waktu sebagai input akan memungkinkan untuk kasus uji dan pemeriksaan lebih mudah?
Luis Mendo
Saya agak bingung apakah ini memperhitungkan tahun kabisat yang diberikan For this, assume February has 28 days and the year is 365 days long., tetapi juga... using the Gregorian calendar.
Destructible Lemon
@DestructibleWatermelon Tidak, ini tidak memperhitungkan tahun kabisat
Beta Decay
dapatkah kita memberikan lebih dari lima tempat desimal?
Destructible Lemon
@DestructibleWatermelon No
Beta Decay

Jawaban:

1

TSQL, 63 byte

Ini adalah versi yang lebih pendek dari jawaban asli saya, karena jawaban pertama saya termasuk perhitungan untuk tahun kabisat.

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

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

Biola

Sql berikut dapat menangani kedua jenis input

TSQL, 154 byte

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))

Fiddle Gabungan 1

Fiddle Gabungan 2

t-clausen.dk
sumber
5

JavaScript (ES6), 84 byte

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>

Dengan asumsi tidak ada tahun kabisat atau DST diperlukan, saya mengganti tahun dengan tahun 1970 yang Date.parsesecara langsung mengembalikan waktu offset dalam milidetik, yang ada 31536000000pada tahun 1970 (atau memang tahun non-kabisat lainnya). Yang perlu saya lakukan adalah menambahkan kembali tahun dan putaran ke 5 tempat desimal. Sunting: Konversi dua arah dalam 183 178 byte:

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>

Asumsikan string yang berisi :format waktu, ditangani seperti di atas, jika tidak dilepaskan tahun, dikonversi ke milidetik, tambahkan setengah menit untuk tujuan pembulatan, dikonversi ke tanggal pada tahun 1970, ekstrak bulan, hari, jam dan menit, dan awali tahun asli.

Neil
sumber
@ βετѧΛєҫαγ Ya, sadalah argumen untuk fungsi.
Neil
Bukankah ini memberikan hasil yang tidak valid, karena tantangan secara eksplisit meminta Februari hanya memiliki 28 hari, dan total 365 hari per tahun?
AdmBorkBork
@TimmyD terkadang februari memiliki 29 hari. Mari kita asumsikan tidak berarti itu dilarang menangani tahun kabisat dengan benar
t-clausen.dk
@ t-clausen.dk Maaf, maksud saya tahun kabisat tidak boleh ditangani
Beta Decay
@ βετѧΛєҫαγ Sekarang tidak menggunakan tahun kabisat atau DST, dan juga memiliki versi reversibel. Apakah itu memuaskan?
Neil
2

Matlab, 132 115 byte

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

Putaran menuju 0.

Hmmm ... Itu cukup panjang.
Itu menggunakan beberapa bawaan, tetapi bukan yang benar-benar bermanfaat - karena tahun kabisat.

Parsing string secara langsung memberikan 2 solusi byte lebih

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

Versi Matlab yang lebih baru mungkin memiliki beberapa fungsi pemisahan yang lebih baik, tapi saya sedang menjalankan 2012a.

Beberapa byte disimpan berkat @Luis Mendo

pajonk
sumber
Anda dapat mendefinisikan array dengan [-1 '# #"#"##"#"'-4]untuk menyimpan beberapa byte. Apakah yearfungsi standar dll? Jika Anda menggunakan kotak alat, Anda harus menunjukkannya dalam judul, misalnya "Matlab dengan Kotak Alat Keuangan"
Luis Mendo
@LuisMendo Saya tidak akrab dengan #notasi dan bahkan tidak pernah menemukannya. Di mana saya dapat membaca lebih banyak tentang hal itu (pencarian cepat Google tidak membantu)? Saya pikir yeardll adalah fungsi standar, tetapi saya tidak tahu apakah mereka berperilaku sama di luar toolbox (docs) .
pajonk
Itu bukan notasi khusus. Hanya string dengan karakter yang memiliki kode ASCII yang sesuai untuk menghasilkan angka yang diperlukan. Sedangkan untuk fungsi, saya tidak tahu, terima kasih telah menjelaskan. Matlab 15b tampaknya tidak memilikinya
Luis Mendo
Oh, itu pintar.
pajonk
1

PowerShell v3 +, 131 byte

$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)

Mengambil input $args[0]dan mengubahnya dengan Get-Dateuntuk menyimpan ke dalam [datetime]format .NET , menyimpan ke $t. Hitung apakah 29 Februari ada, dan set $ajadi kami kurangi nilai menit pada tanggal tersebut (jika ada).

Kemudian kami menggunakan -foperator ormat dengan spesifikasi string tetap 5 angka desimal untuk menjalankan perhitungan. Gunakan built-in untuk menghitung .DayOfYeardan .TotalMinutesdari input yang diberikan, kurangi $ajika ini tahun kabisat, bagi dengan 525600total menit, dan tambahkan pada input .Year.

Akan mengeluh (secara lisan) kepada STDERR jika 29 Februari tidak ada (lihat contoh di bawah), tetapi karena STDERR diabaikan secara default, kami tidak khawatir tentang itu. Juga, perhatikan bahwa PowerShell melakukan pembulatan bankir secara default.

Contohnya

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

Bergantian, dengan tahun kabisat, 119 byte

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

Jika kita mengikuti pengaturan kalender, kita dapat mengurangi selusin byte karena kita tidak perlu memperhitungkan $adalam kode asli di atas. Ini memungkinkan kami untuk pindah $tke ekspresi itu sendiri, dan kami akan secara eksplisit menghitung .DayOfYearuntuk tanggal 31 Desember. Jika tidak, ikuti metodologi yang sama.

AdmBorkBork
sumber
0

Python 3, 163 173 byte

lebih banyak byte karena format output

tidak menggunakan tanggal bawaan apa pun, seperti jawaban 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

sedikit lebih mudah dibaca

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
Lemon dirusak
sumber
0

Perl 6 ,  107 105  102 byte

{$/=.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⁵}

Penjelasan:

{
  $/ = .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
}

Uji:

#! /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
sumber