Мы тогда еще?

22

Я путешественник во времени, и я одержим течением времени. Мне особенно нравятся моменты, когда стрелки часов проходят 12, или когда я переворачиваюсь на следующую страницу моего календаря, или когда все кричат ​​"С Новым годом!"

Пожалуйста, напишите мне программу, которая покажет мне, как далеко я от последнего такого момента до следующего, в форме индикатора выполнения. Например, если я скажу, что время 09:12, оно должно напечатать это:

09:00 ####---------------- 10:00

Если я скажу, что месяц май 1982 года, он должен напечатать это:

1982-01 #######------------- 1983-01

Я упоминал, что я путешественник во времени? Я путешествую в любую точку от первой миллисекунды 0 г. н.э. до последней миллисекунды 9999 г. н.э., поэтому программа должна обрабатывать любую дату и время в этом диапазоне.

вход

  • Ввод будет в одном из следующих форматов:

    • YYYY-MM-DDThh:mm:ss.sss
    • YYYY-MM-DDThh:mm:ss
    • YYYY-MM-DDThh:mm
    • YYYY-MM-DDThh
    • YYYY-MM-DD
    • YYYY-MM

    Это единственные форматы, которые необходимо обрабатывать. Каждая часть будет иметь точное количество отображаемых цифр, что означает, что дробные секунды могут иметь конечные нули (например .120, никогда .12). TЯвляется буквальной буквой «Т» , ограничивающая дату от времени. Часы работают круглосуточно.

  • Месяцы и дни основаны на 1 (подробнее об этом ниже).

  • Неправильные и находящиеся вне диапазона входные данные не должны обрабатываться.

  • По усмотрению программиста, ввод может иметь один завершающий перевод строки.

Прогресс бар математика

Программа касается наименее и второстепенно значимых единиц в данном входе. Например, если ввод имеет точность на уровне дня (например 2016-12-14), индикатор выполнения укажет, какая доля дней во входном месяце истекла по сравнению с тем, что осталось.

Индикатор выполнения будет иметь 20 единиц (символов), а представленная пропорция будет округлена до ближайшего приращения 120 . Например, с учетом того 2016-12-14T12:28, индикатор будет показывать раунд ( 28 / 60 × 20) = 9 из 20 единиц "заполнены."

1 на основе месяцев и дней

Хотя день 1 декабря (к примеру) находится 01в 2016-12-01, с целью расчета является 0 - й день месяца, потому что укороченные блоки означают 0 - й милисекнду 0 - й минуте 0 - й час дня. Другими словами, 2016-12-01это 0 / 31 пути до декабря и 2016-12-02составляет 1 / +31 , и так далее.

Кроме того, 2016-01это 0th миллисекунду в 0 - й день января, поэтому в расчетах 0 / 12 , что означает , 2016-12это 11 / 12 .

Да, это означает, что месяцы и дни никогда не будут полностью заполнять индикатор выполнения.

Различная продолжительность месяца и високосные годы

Разные месяцы имеют разное количество дней, и результаты должны отражать это, включая високосные годы. Индикатор выполнения на 6 февраля 2017 г. будет отличаться от индикатора выполнения на 6 февраля 2016 г. (или 6 января обоих лет).

Разнообразный

Выход

Программа (или функция) должна напечатать (или вернуть в виде строки) горизонтально ориентированный 20-символьный индикатор выполнения, который «заполняется» за прошедшее время и «открывается» за оставшееся время. Оно должно «заполняться» слева направо.

Индикатор выполнения должен иметь метку слева, показывающую начало отсчитываемого периода, а другую справа от него, показывающую начало следующего периода, в том же формате, что и ввод (но показывающий только две единицы точности). Для нашего примера 2016-12-14допустимый результат будет:

12-01 #########----------- 01-01

Вот допустимые форматы меток для каждого из возможных периодов:

  • Месяцы: YYYY-MM
  • Дни: MM-DD
  • часы работы: DDThh
  • Минуты: hh:mm
  • секунды: mm:ss
  • миллисекунды: ss.sss

Никакие дополнительные единицы не могут быть включены в метки, и ни одна не может быть опущена.

Вывод заметок

  • «Заполненные» единицы индикатора выполнения будут представлены #персонажем. «Открытые» единицы будут представлены -.
  • Между индикатором выполнения и каждой меткой должен быть ровно один пробел.
  • Допускаются начальные или конечные пробелы и / или один завершающий символ новой строки.

выигрыш

Это . Самый короткий код в байтах побеждает. Стандартные правила применяются. Стандартные лазейки запрещены.

Примеры

Input                      Output
-----------------------    -------------------------------------
2016-12-12T12:17           12:00 ######-------------- 13:00
2016-12-12                 12-01 #######------------- 01-01
0000-01-01T00:00:00.000    00.000 -------------------- 01.000
0000-01-01T00:00           00:00 -------------------- 01:00
1899-12-31T23              31T00 ###################- 01T00
1899-12-31                 12-01 ###################- 01-01
1899-12                    1899-01 ##################-- 1900-01
1982-05-15T17:15           17:00 #####--------------- 18:00
1982-05-15T17              15T00 ##############------ 16T00
1982-05                    1982-01 #######------------- 1983-01
9999-12-31T23:59:59.999    59.000 #################### 00.000
9999-12                    9999-01 ##################-- 10000-01
2000-01-06                 01-01 ###----------------- 02-01
2000-02-06                 02-01 ###----------------- 03-01
2001-02-06                 02-01 ####---------------- 03-01
1742-09-10                 09-01 ######-------------- 10-01
Иордания
источник
4
Должны ли мы беспокоиться о високосных секундах?
Райли
@ Райли Хороший вопрос. Нет
Иордания
2
Я предполагаю, что летнее время игнорируется, поскольку нет единой стандартизированной формы?
CAD97
3
@ CAD97 Хороший вопрос. Ты прав. DST действительно усложняет жизнь путешественникам во времени, поэтому мы игнорируем это.
Джордан
Пример «1899-12-31T23» недопустим согласно предоставленному списку форматов ввода, то же самое для «1982-05-15T17». Пожалуйста, проверьте ваши тестовые данные.
Цеппелин

Ответы:

4

JavaScript, 282 байта

(x,v=x.split(/\D/g),l=v.length-2,[a,b,c,d]=("10e5,01,-,12,01,-,"+new Date(v[0],v[1],0).getDate()+",00,T,24,00,:,60,00,:,60,000,.,1000").split`,`.slice(l*3,l*3+4),t=(v[l+1]-b)/d*20+.5|0,n=v[l],o=((n|0)+1)%a,r=l?('0'+o).slice(-2):o)=>n+c+b+' '+'#'.repeat(t)+'-'.repeat(20-t)+' '+r+c+b

Проходит все тесты

(
x,
v=x.split(/\D/g),
l=v.length-2,
[a,b,c,d]=("10e5,01,-,12,01,-,"+new Date(v[0],v[1],0).getDate()+",00,T,24,00,:,60,00,:,60,000,.,1000").split`,`.slice(l*3,l*3+4),
t=(v[l+1]-b)/d*20+.5|0,
n=v[l],
o=((n|0)+1)%a,
r=l?('0'+o).slice(-2):o
) =>n+c+b+' '+'#'.repeat(t)+'-'.repeat(20-t)+' '+r+c+b

Тестовая функция ничего не печатает для прохода, значения для неудачи.

function test(value,expected){
    if (f(value)!=expected)
    {
        console.log(value);
        console.log(f(value));
        console.log(expected);
     }
}

Тестовые случаи:

test('2016-12-12T12:17','12:00 ######-------------- 13:00')                 ;
test('2016-12-12','12-01 #######------------- 01-01')                       ;
test('0000-01-01T00:00:00.000','00.000 -------------------- 01.000')        ;
test('0000-01-01T00:00','00:00 -------------------- 01:00')                 ;
test('1899-12-31T23','31T00 ###################- 01T00')                    ;
test('1899-12-31','12-01 ###################- 01-01')                       ;
test('1899-12','1899-01 ##################-- 1900-01')                      ;
test('1982-05-15T17:15','17:00 #####--------------- 18:00')                 ;
test('1982-05-15T17','15T00 ##############------ 16T00')                    ;
test('1982-05','1982-01 #######------------- 1983-01')                      ;
test('9999-12-31T23:59:59.999','59.000 #################### 00.000')        ;
test('9999-12','9999-01 ##################-- 10000-01')                     ;
test('2000-01-06','01-01 ###----------------- 02-01')                       ;
test('2000-02-06','02-01 ###----------------- 03-01')                       ;
test('2001-02-06','02-01 ####---------------- 03-01')                       ;
test('1742-09-10','09-01 ######-------------- 10-01')                       ;
Grax32
источник
2
Я должен был выучить новый язык, чтобы превысить эту версию ... это очень кратко!
Рексрони
3

Pyth, 213 байтов

Мой первый код в Pyth! Вот:

+%h=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lKr:w"[-T:.]"d7 3*2lKJ@K_2+@N1+%eN=b<lK4+d+*\#=Gs+*20c-eKb@=H[0^9T12?q2=k@K1+28+q0%=YhK4-q0%Y400q0%Y100+30%+k/k8 2 24 60 60 999)lK.5+*\--20G+d+%hN%+J1@H-lK1+@N1%eNb

Мой pyth-код тесно связан с моим предыдущим Python-ответом. Вот негольфированная версия с комментариями:

"K is the input, as a list of numbers"
Kr:w"[-T:.]"d7
"Y=year"
=YhK
"k=month"
=k@K1
"H = a list of denominators"
=H[0 ^9T 12 ?q2k+28+q0%Y4-q0%Y400q0%Y100 +30%+k/k8 2 24 60 60 999)
"J is the second-to-last number of the input"
J@K_2
"b is the +1 starting point for months and days"
=b<lK4
"G is the number of hashtags in the statusbar"
=Gs+*20c-eKb@HlK.5
"N is the formatted string"
=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lK3 *2lK
+%hNJ+@N1+%eNb+d+*\#G+*\--20G+d+%hN%+J1@H-lK1+@N1%eNb

Тестирование нескольких значений легко выполнить, выполнив цикл кода и добавив в конец символ новой строки:

Wp+%h=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lKr:w"[-T:.]"d7 3*2lKJ@K_2+@N1+%eN=b<lK4+d+*\#=Gs+*20c-eKb@=H[0^9T12?q2=k@K1+28+q0%=YhK4-q0%Y400q0%Y100+30%+k/k8 2 24 60 60 999)lK.5+*\--20G+d+%hN%+J1@H-lK1+@N1+%eNb"\n"

Тогда я побежал cat testinput | pyth code.pyth > outputи diff output testoutput или попробуйте онлайн .

rexroni
источник
2

Python 2, 371 байт

Этот вызов был удивительно сложным! Казалось, что мне будет чуть меньше 300, пока я не отработаю форматирование выходной строки.

Самое интересное, что мой ответ не использует пакет даты:

import re
s=raw_input()
S=[int(i)for i in re.sub('[-T:.]',' ',s).split()]
l=len(S)
y,m=S[:2]
d=[0,20<<9,12,28+(y%4==0!=y%100)+(y%400==0)if m==2else 30+(m+m/8)%2,24,60,60,999]
a,n=S[-2:]
b=1-(1if l>3else 0)
h=int(20.*(n-b)/d[l]+.5)
x,y,z='- %.4d - %.2d - %.2d T %.2d : %.2d : %.2d . %.3d'.split()[l*2-3:l*2]
print x%a+y+z%b+' '+'#'*h+'-'*(20-h)+' '+x%((a+1)%d[l-1])+y+z%b
rexroni
источник