A contagem regressiva do dia de trabalho

17

Eu tinha uma idéia genial para facilitar a vida profissional - uma contagem regressiva para uma data específica que conta apenas dias úteis.


A tarefa básica é criar uma contagem regressiva para uma data específica que inclua apenas os dias úteis na contagem regressiva.

Como o dia útil conta segunda , terça , quarta , quinta e sexta - feira .

A Entrada deve ser uma data específica no formato padrão europeu "não oficial" dd.MM.yyyye deve ser hoje ou um dia no futuro.

A saída deve ser apenas o número de dias restantes.

Como é o código mais curto vence.


Caso de teste:

  Today    |   Input    | Output
10.12.2018 | 17.12.2018 |    5
02.10.2018 | 16.10.2018 |   10

Se eu perdi algumas coisas na pergunta, por favor me perdoe - é a minha primeira pergunta :)

EDITAR:

  • Você pode usar falsecomo saída em vez de 0 <- mas não é bonito
  • Não há necessidade de respeitar o horário de verão
Hille
fonte
9
Existe alguma razão específica por trás desse formato de entrada europeu "não oficial" ? Nosso consenso é permitir contribuições flexíveis sempre que possível.
Arnauld
6
Existe realmente algum sentido em adicionar o "desafio extra" de um formato de data difícil de processar? Que apenas parece línguas wrt injustas que têm formatos de data flexíveis ...
Quintec
3
@Hille Eu não disse que era "difícil", é apenas um aborrecimento desnecessário, especialmente no código-golfe ... observe o link que Arnauld postou acima ... geralmente a entrada flexível é a norma ...
Quintec
6
A propósito, você observa que este é seu primeiro desafio; Convido você a usar o Sandbox para aperfeiçoar antes de postar um desafio ao main! Caso contrário, bom trabalho, e eu gostarei de ver um pouco mais de você!
Giuseppe
7
Não é realmente impressionado com o formato de entrada estrito, mas que não seja um bom desafio.
ElPedro 01/10

Respostas:

18

05AB1E , 130 128 133 131 124 123 bytes

žežfžg)V0[Y`UÐ3‹12*+>13*5÷s3‹Xα©т%D4÷®т÷©4÷®·()ćsO7%2@+Y`т‰0Kθ4ÖUD2Qi\28X+ë<7%É31α}‹iY¬>0ëY1¾ǝDÅsD12‹i>1ë\1Dǝ¤>2}}ǝVYI'.¡Q#

Estou maluco ..

Para o idioma de golfe 05AB1E, não importa se a entrada está com .ou -. No entanto, 05AB1E não possui nenhum built-in para objetos ou cálculos de data. O único construído em relação às datas que possui é o ano / mês / dia / hora / minutos / segundos / microssegundos de hoje.

Portanto, por causa disso, quase todo o código que você vê são cálculos manuais para ir para o dia seguinte e calcular o dia da semana.

+5 bytes devido a uma parte que esqueci na fórmula de Zeller (ano-1 para os meses de janeiro e fevereiro).

Experimente online ou Experimente online com uma data emulada e especificada automaticamente de 'hoje' .

Explicação:

Parede de entrada de texto.

Em geral, o código segue o seguinte pseudocódigo:

1   Date currentDate = today;
2   Integer counter = 0;
3   Start an infinite loop:
4*    If(currentDate is NOT a Saturday and currentDate is NOT a Sunday):
5       Counter += 1;
6*    currentDate += 1; // Set currentDate to the next day in line
7     If(currentDate == parsed input-string):
8       Stop the infinite loop, and output the counter

1) Date currentDate = today;faz parte do programa 05AB1E:

že          # Push today's day
  žf        # Push today's month
    žg      # Push today's year
      )     # Wrap them into a single list
       V    # Pop and store this list in variable `Y`

2) Integer counter = 0;e 3) Start an infinite loop:são diretas no programa 05AB1E:

0     # Push 0 to the stack
 [    # Start an infinite loop

4) If(currentDate is NOT a Saturday and currentDate is NOT a Sunday):é a primeira parte difícil com cálculos manuais. Como 05AB1E não possui data embutida, teremos que calcular o dia da semana manualmente.

A fórmula geral para fazer isso é:

h=(q+13(m+1)5+K+K4+J42J)mod7,

Onde, para os meses de março a dezembro:

  • q é oday do mês ([1, 31])
  • m é o 1-indexadamonth ([3, 12])
  • K é o ano do século (yearmod100 )
  • J é o século 0-indexada (year100)

E para os meses de janeiro e fevereiro:

  • q é oday do mês ([1, 31])
  • m é o 1-indexadamonth+12 ([13, 14])
  • K é o ano do século para o ano anterior ((year1)mod100 )
  • J é o século indexado em 0 para o ano anterior (year1100 )

Resultando no dia da semana h , em que 0 = sábado, 1 = domingo, ..., 6 = sexta-feira.
Fonte: congruência de Zeller

Podemos ver isso nesta parte do programa 05AB1E:

Y             # Push variable `Y`
 `            # Push the day, month, and year to the stack
  U           # Pop and save the year in variable `X`
   Ð          # Triplicate the month
    3        # Check if the month is below 3 (Jan. / Feb.),
              # resulting in 1 or 0 for truthy/falsey respectively
      12*     # Multiply this by 12 (either 0 or 12)
         +    # And add it to the month
              # This first part was to make Jan. / Feb. 13 and 14

>             # Month + 1
 13*          # Multiplied by 13
    5÷        # Integer-divided by 5
s3           # Check if the month is below 3 again (resulting in 1 / 0)
   Xα         # Take the absolute difference with the year
     ©        # Store this potentially modified year in the register
      т%      # mYear modulo-100
D4÷           # mYear modulo-100, integer-divided by 4
®т÷©4÷        # mYear integer-divided by 100, and then integer-divided by 4
®·(           # mYear integer-divided by 100, doubled, and then made negative
)             # Wrap the entire stack into a list
 ć            # Extract the head (the counter variable that was also on the stack)
  s           # Swap so the calculated values above are as list at the top
   O          # Take the sum of this entire list
    7%        # And then take modulo-7 to complete the formula,
              # resulting in 0 for Saturday, 1 for Sunday, and [2, 6] for [Monday, Friday]

2@            # Check if the day is greater than or equal to 2 (so a working day)

5) Counter += 1;é direto novamente:

     # The >=2 check with `2@` results in either 1 for truthy and 0 for falsey
+    # So just adding it to the counter variable is enough

6) currentDate += 1; // Set currentDate to the next day in lineé novamente mais complexo, porque temos que fazer isso manualmente. Portanto, isso será expandido para o seguinte pseudocódigo:

a   Integer isLeapYear = ...;
b   Integer daysInCurrentMonth = currentDate.month == 2 ?
c                                 28 + isLeapYear
d                                :
e                                 31 - (currentDate.month - 1) % 7 % 2;
f   If(currentDate.day < daysInCurrentMonth):
g     nextDate.day += 1;
h   Else:
i     nextDate.day = 1;
j     If(currentDate.month < 12):
k       nextDate.month += 1;
l     Else:
m       nextDate.month = 1;
n       nextDate.year += 1;

Fontes:
Algoritmo para determinar se um ano é um ano bissexto. (EDIT: não é mais relevante, pois uso um método alternativo para verificar os anos bissextos que salvaram 7 bytes.)
Algoritmo para determinar o número de dias em um mês.

6a) Integer isLeapYear = ...;é feito assim no programa 05AB1E:

Y             # Push variable `Y`
 `            # Push the days, month and year to the stack
  т‰          # Divmod the year by 100
    0K        # Remove all items "00" (or 0 when the year is below 100)
      θ       # Pop the list, and leave the last item
       4Ö     # Check if this number is visible by 4
         U    # Pop and save the result in variable `X`

Também usado em nesta minha resposta 05AB1E , para que alguns anos de exemplo sejam adicionados para ilustrar as etapas.

6b) currentDate.month == 2 ?e 6c) 28 + isLeapYearsão feitos assim:

D            # Duplicate the month that is now the top of the stack
 2Q          # Check if it's equal to 2
   i         # And if it is:
    \        #  Remove the duplicated month from the top of the stack
     28X+    #  Add 28 and variable `X` (the isLeapYear) together

6d) :e 6e) 31 - (currentDate.month - 1) % 7 % 2;são feitos assim:

ë           # Else:
 <          #  Month - 1
  7%        #  Modulo-7
    É       #  Is odd (shortcut for %2)
     31     #  Push 31
       α    #  Absolute difference between both
}           # Close the if-else

6f) If(currentDate.day < daysInCurrentMonth):é feito assim:

     # Check if the day that is still on the stack is smaller than the value calculated
 i    # And if it is:

6g) nextDate.day += 1;é feito assim:

Y       # Push variable `Y`
 ¬      # Push its head, the days (without popping the list `Y`)
  >     # Day + 1
   0    # Push index 0

        # (This part is done after the if-else clauses to save bytes)
}}      # Close the if-else clauses
  ǝ     # Insert the day + 1 at index 0 in the list `Y`
   V    # Pop and store the updated list in variable `Y` again

6h) Else:e 6i) nextDate.day = 1;são feitas da seguinte maneira:

ë        # Else:
 Y       #  Push variable `Y`
  1      #  Push a 1
   ¾     #  Push index 0
    ǝ    #  Insert 1 at index 0 (days part) in the list `Y`

6j) If(currentDate.month < 12)::

D           # Duplicate the list `Y`
 Ås         # Pop and push its middle (the month)
   D12     # Check if the month is below 12
       i    # And if it is:

6k) nextDate.month += 1;:

>       # Month + 1
 1      # Push index 1

        # (This part is done after the if-else clauses to save bytes)
}}      # Close the if-else clauses
  ǝ     # Insert the month + 1 at index 1 in the list `Y`
   V    # Pop and store the updated list in variable `Y` again

6l) Else:, 6m) nextDate.month = 1;e 6n) nextDate.year += 1;são feitos da seguinte maneira:

ë        # Else:
 \       #  Delete the top item on the stack (the duplicated month)
  1      #  Push 1
   D     #  Push index 1 (with a Duplicate)
    ǝ    #  Insert 1 at index 1 (month part) in the list `Y`

 ¤       #  Push its tail, the year (without popping the list `Y`)
  >      #  Year + 1
   2     #  Index 2

         # (This part is done after the if-else clauses to save bytes)
}}       # Close the if-else clauses
  ǝ      # Insert the year + 1 at index 2 in the list `Y`
   V     # Pop and store the updated list in variable `Y` again

E finalmente às 8) If(currentDate == parsed input-string):e 9) Stop the infinite loop, and output the counter:

Y          # Push variable `Y`
 I         # Push the input
  '.¡     '# Split it on dots
     Q     # Check if the two lists are equal
      #    # And if they are equal: stop the infinite loop
           # (And output the top of the stack (the counter) implicitly)
Kevin Cruijssen
fonte
5
Você é um louco ... tem um voto positivo.
AdmBorkBork
1
O programa 05AB1E mais longo de todos os tempos?
Luis Mendo
2
@LuisMendo Close, mas tenho medo de ter uma resposta 05AB1E que é ainda mais longa e que chega muito perto .. ;) Tenho certeza de que poderei jogar alguns bytes aqui e simplificar partes da implementação do pseudo-código do dia seguinte. Vai olhar amanhã de manhã, mas acabou de voltar do esporte e vai dormir em breve.
Kevin Cruijssen
11

Excel 24 bytes

Pressupõe entrada na célula A1

=NETWORKDAYS(NOW()+1,A1)

Usa a função interna. Infelizmente, a função inclui hoje e a data final. Desde então, o OP esclareceu para não contar hoje, então adiciono um ao NOW para não contar hoje.

Para endereçar comentários no formato de número, novamente, este é o padrão do Excel: insira a descrição da imagem aqui

Keeta - restabelecer Monica
fonte
Embora isso funcione com valores de data, ele falha ao receber a entrada conforme indicado. Ou seja (pelo menos na versão dos EUA) 10.12.2018é uma string quando mantida em uma célula e não em uma data. A solução óbvia, mas muito tempo para corrigir este seria mudar A1a DATE(RIGHT(A1,4),MID(A1,4,2),LEFT(A1,2))sua solução
Taylor Scott
infelizmente, a comunidade decidiu que os idiomas precisam ser executados sob as configurações padrão para serem válidos (a única exceção que eu já vi sobre isso é o idioma - IE, se seu idioma suportar inglês e espanhol, você poderá usá-lo facilmente, mas . isso deve ser observado) Além disso, OP (@hille) não indicou que o formato é flexível, e tem, de facto, declarou o oposto (ver segundo comentário sobre esta questão)
Taylor Scott
2
O formato não é padrão, é baseado em localidade. O Excel lê o formato da HKCU\Control Panel\International\sDecimalcadeia de registro. Em uma instalação padrão do Windows nos EUA, é MM / dd / aaaa. Na maioria dos países da UE, esse seria o padrão.
Erik A
@luisMendo Sim, isso funciona. Não vi nenhum esclarecimento. Se não fosse contar no dia anterior, eu poderia ter = NETWORKDAYS (NOW (), A1-1). Eu sabia que sempre seria a mesma contagem de bytes, independentemente do esclarecimento.
Keeta - reinstala Monica
Ainda bem que funciona. Eu removi o voto negativo
Luis Mendo
8

Java 10, 233 232 226 bytes

import java.util.*;d->{int r=0;var s=Calendar.getInstance();s.setTime(new Date());var e=s.getInstance();for(e.setTime(new java.text.SimpleDateFormat("dd.MM.yyyy").parse(d));!s.after(e);s.add(5,1))if(s.get(7)%7>1)r++;return r;}

Date sempre me lembra como Java é realmente detalhado ..

NOTA: Agora existem duas respostas Java mais curtas (abaixo de 175 bytes), uma com uso inteligente de métodos descontinuados de versões anteriores do Java por @LukeStevens e outra usando as java.time.LocalDatenovidades desde o Java 8 por @ OlivierGrégoire .

Experimente online.

Explicação:

import java.util.*;            // Required import for both Calendar and Date
d->{                           // Method with String parameter and integer return-type
  int r=0;                     //  Result-integer, starting at 0
  var s=Calendar.getInstance();//  Create a Calendar instance for the start-date
  s.setTime(new Date());       //  Set the start date to today
  var e=s.getInstance();       //  Create a Calendar instance for the end-date
  for(e.setTime(               //  Set the end date to:
        new java.text.SimpleDateFormat("dd.MM.yyyy")
                               //   Create a formatter for the "dd.MM.yyyy" format
         .parse(d));           //   And parse the input-String to a Date
      !s.after(e)              //  Loop as long as we haven't reached the end date yet
      ;                        //    After every iteration:
       s.add(5,1))             //     Increase the start-date by 1 day
    if(s.get(7)%7>1)           //   If the day of the week is NOT a Saturday or Sunday:
                               //   (SUNDAY = 1, MONDAY = 2, ..., SATURDAY = 7)
      r++;                     //    Increase the result-sum by 1
  return r;}                   //  Return the result-sum
Kevin Cruijssen
fonte
Você poderia fazer e=s.clone()?
Quintec
1
Também podemos (suponho) fazer Calendar s=Calendar.getInstance(),e=s.getInstance(), que infelizmente acaba sendo exatamente do mesmo tamanho.
Misha Lavrov
1
@MishaLavrov Ah, a estática Crealmente não é necessária. Era de uma parte antiga do código onde eu também usava Cem outro lugar. Foi capaz de golf 1 byte usando var s=Calendar.getInstance();var e=s.getInstance();tão obrigado. :)
Kevin Cruijssen
1
150 bytes , usando java.time.
Olivier Grégoire
1
Feito! É muito próximo em bytes à outra resposta, mas ainda não a supera.
Olivier Grégoire
7

JavaScript (ES6), 116 103 bytes

f=(d,n=+new Date)=>(D=new Date(n)).toJSON()<d.split`.`.reverse().join`-`&&(D.getDay()%6>0)+f(d,n+864e5)

Experimente online!

Quão?

n .

nD.toJSON() método:

AAAA - MM - DD T hh : mm : ss.sss Z

YYYY-MM-DDdYYYY-MM-DDDD.MM.YYYY

d.split`.`.reverse().join`-`

D.getDay()0606

(D.getDay() % 6 > 0) + f(d, n + 864e5)

86,400,000n

Arnauld
fonte
6

MATL , 24 bytes

46tQZt24&YO:Z':X-9XO83-z

Experimente online!

Eu não quero ter nenhum formato de entrada para que linguagens de golfe com códigos específicos tenham uma grande vantagem

Você meio que conseguiu :-)

Explicação

46      % Push 46 (ASCII for '.')
tQ      % Duplicate, add 1: gives 47 (ASCII for '/')
Zt      % Implicit input. Replace '.' by '/' in the input string
24&YO   % Convert string with date format 24 ('dd/mm/yyyy') to serial date number.
        % This is an integer representing day starting at Jan-1-0000
:       % Inclusive range from 1 to that
Z'      % Push current date and time as a serial number. Integer part is day;
        % decimal part represents time of the day
:       % Inclusive range from 1 to that
X-      % Set difference. Gives serial numbers of days after today, up to input
9XO     % Convert each number to date format 9, which is a letter for each day
        % of the week: 'M', 'T', 'W', 'T', ' F', 'S', 'S'
83-     % Subtract 83 (ASCII for 'S')
z       % Number of nonzeros. Implicit display
Luis Mendo
fonte
Se entendi o desafio corretamente, você pega apenas uma entrada de data e a compara com a data de hoje. Por exemplo, 16.10.2018hoje (segunda-feira 01-10-2018) resultaria em 11amanhã em 10etc.
Kevin Cruijssen 01/10/1918
@KevinCruijssen Whoops. Obrigado! Corrigido agora
Luis Mendo
1
E com a mesma contagem de bytes. :) Legal, +1 de mim.
Kevin Cruijssen 01/10/1918
6

Wolfram Language (Mathematica) , 64 56 bytes

DayCount[Today,""<>#~StringTake~{{4,6},3,-4},"Weekday"]&

Experimente online!

DayCount[x,y,"Weekday"]conta o número de dias da semana entre xe y.

As entradas xe ypodem ser muitas coisas, incluindo uma fantasia DateObjectcomo a retornada porToday , ou uma string no formato (infelizmente) mm.dd.yyyy.

Minha tentativa anterior tentou ativar o dd.mm.yyyy entrada em uma DateObject, dizendo ao Mathematica como analisá-la; a nova solução simplesmente reorganiza a string para colocar dia e mês na ordem que o Mathematica espera.

Vale ressaltar que a solução de 28 bytes DayCount[Today,#,"Weekday"]&não só funciona perfeitamente para um formato de entrada mês-dia-ano, mas também lida corretamente com entradas inequívocas de dia-mês-ano como 31.12.2018, o que não poderia significar "o 12º dia do 31º dia mês". Por isso, é correto mais de 60% das vezes :)

Misha Lavrov
fonte
5

Perl 6 , 61 bytes

{+grep 6>*.day-of-week,Date.today^..Date.new(|[R,] m:g/\d+/)}

Experimente online!

Nwellnhof
fonte
5

R, 72 caracteres

Uma variação na resposta fornecida por @ngm, que evita que o grepl salve alguns caracteres e funcione em locais que não sejam em inglês.

sum(strftime(seq(Sys.Date(),as.Date(scan(,""),"%d.%m.%Y"),1),'%u')<6)+1

Neal Fultz
fonte
1
Mais curto e mais geral também. Boa resposta e bem-vindo ao asilo.
Ng4 /
1
Bem-vindo ao PPCG! você pode adicionar um link de TIO - é fácil e formata a resposta para você :)
Jayce
5

Java (OpenJDK 8) , 174 166 165 bytes

Com um pouco de inspiração na resposta de Kevin e uma boa análise através da API obsoleta do Date, consegui obter uma solução Java mais sucinta.

-8 bytes graças à análise inventiva da data regex de Kevin

-1 bytes graças à inteligente operação bit a bit de Nevay

import java.util.*;d->{long r=0,s=new Date().getTime(),e=Date.parse(d.replaceAll("(..).(..).","$2/$1/"));for(;s<=e;s+=864e5)r-=-new Date(s).getDay()%6>>-1;return r;}

Experimente online!

Explicação

import java.util.*;                         // Required import for Date 
long r=0,                                   // Initialise result variable
     s=new Date().getTime(),                // Current date in millis
     e=Date.parse(
         d.replaceAll("(..).(..).","$2/$1/")// Use regex to convert to MM/dd/yyyy
     );                                     // Parse date arg using deprecated API
for(;s<=e;                                  // Loop while current millis are less than date arg (e.g. date is before)       
    s+=864e5)                               // Add 86400000 ms to current date (equiv of 1 day)
    r-=-new Date(s).getDay()%6>>-1;        // If day is Sunday (0) or Saturday (6) don't increment, else add 1
return r;                                   // When loop finished return result
Luke Stevens
fonte
1
Boa resposta! Uso inteligente das varargs com os formatos d=d[0].splitobsoleto e obsoleto .parsecom o formato padrão MM/dd/yyyy. Um pequeno erro na sua postagem, você tem em import java.text.*;vez do import java.util.*;código e // Required import for both Calendar and Dateda explicação (mesmo que não use Calendar).
Kevin Cruijssen
@KevinCruijssen Não faço ideia do porquê eu tinha java.textreparado agora! Obrigado!
Luke Stevens
1
Embora eu tenha gostado do d=d[0].splitvarargs, alterar a entrada para uma String regular, remover d=d[0].split("\\.");e alterar d[1]+"/"+d[0]+"/"+d[2]para d.replaceAll("(..).(..).","$2/$1/") salva 7 bytes .
Kevin Cruijssen
1
E mais 1 byte , alterando r+=new Date(s).getDay()%6<1?0:1,s+=864e5);para s+=864e5)r+=new Date(s).getDay()%6<1?0:1;. :)
Kevin Cruijssen
1
-1 byte:r-=-new Date(s).getDay()%6>>-1;
Nevay
4

Vermelho , 72 bytes

func[a][b: now/date s: 0 until[if b/weekday < 6[s: s + 1]a < b: b + 1]s]

Experimente online!

Leva a data no formato dd-mm-aaaa, por exemplo 31-10-2018 (também funciona com 10 de outubro de 2018)

Entrada estrita:

Vermelho , 97 bytes

func[a][a: do replace/all a".""-"b: now/date s: 0 until[if b/weekday < 6[s: s + 1]a < b: b + 1]s]

Experimente online!

Bônus:

Retorna uma lista das datas / dias da semana dos dias úteis até a data especificada:

Vermelho , 235 bytes

f: func [ a ] [
    b: now/date
    d: system/locale/days
    collect [ 
        until [ 
            if b/weekday < 6 [ 
                keep/only reduce [ b ":" d/(b/weekday) ]
            ]
            a < b: b + 1
        ]
    ]
]

Experimente online!

Galen Ivanov
fonte
Agh, não é justo, em python eu preciso gastar cerca de 72 bytes processando este formato IO ...: P
Quintec 1/18/18
1
Normalmente as minhas soluções vermelhas estão entre os mais longos, mas felizmente Red ofertas muito bem com datas :)
Galen Ivanov
1
90 bytes para processar python ... eu terminei, parei até que houvesse um formato de entrada mais flexível: P
Quintec 1/18/18
3

Python 2 , 163 156 149 147 bytes

lambda s:sum((date.today()+timedelta(x)).weekday()<5for x in range((date(*map(int,(s.split(".")[::-1])))-date.today()).days))
from datetime import*

Experimente online!

-7 com agradecimentos a @mypetlion

-7 mais com graças a @ovs

+30 devido ao formato de entrada muito restritivo, que eu notei apenas antes de postar meu código anterior, que recebeu entrada como por exemplo (2018,11,1):-(

ElPedro
fonte
2
Não há necessidade para isso: (0,1)[t.weekday()<5]. Os booleanos Python são uma subclasse inte True, Falsepodem ser usados ​​em operações aritméticas como 1,0. Substitua por c+=t.weekday()<5para salvar 7 bytes.
mypetlion
1
149 bytes como um lambda.
ovs 01/10/1918
Obrigado @mypetlion. Eu não deveria ter perdido essa.
ElPedro 01/10
Obrigado @ovs. Segunda vez, você ajudou recentemente. A última vez foi um impressionante -30. Estava tentando descobrir como colocar isso em um lambda.
ElPedro 01/10
3

Java (JDK 10) , 171 bytes

s->{int c=0;for(var t=java.time.LocalDate.now();!t.parse(s.replaceAll("(..).(..).(.*)","$3-$2-$1")).equals(t);t=t.plusDays(1))c-=t.getDayOfWeek().getValue()/6-1;return c;}

Experimente online!

Créditos

Olivier Grégoire
fonte
1
Você pode mudar (.*)\\.(.*)\\.(.*)para (..).(..).(.*).
Kevin Cruijssen
Com sua replaceAlltécnica, sua resposta também pode ser alterada em 7 bytes, portanto a sua ainda é um pouco mais longa. ;)
Kevin Cruijssen
@KevinCruijssen Obrigado pela regex! E não se preocupe: eu não me importo de ter uma resposta mais longa;)
Olivier Grégoire
3

JavaScript (Node.js) , 168 160 139 133 bytes

35 bytes a menos graças a Quintec e Kevin Cruijssen

D=>{var i=D.split('.'),n=0;for(var d=new Date();d<=new Date(i[2],i[1]-1,i[0]);d.setDate(d.getDate()+1))n+=-~d.getDay()%7>1;return n;}

Experimente online!

D=>{
  var i=D.split('.'),                 // Splits the date string by .
      n=0;                            // Counter variable
  for(var d=new Date();               // For the actual date
      d<=new Date(i[2],i[1]-1,i[0]);      // As long as the date is less or equal the requested date
      d.setDate(d.getDate()+1))           // Count the date one up
    n+=-~d.getDay()%7>1;                // If the date is not a Sunday or Saturday
  return n;                           // Return the counter variable
}
Hille
fonte
1
158 bytes com lambda
Quintec
1
139 bytes com condição if melhorada
Quintec
1
Como seu método não é recursivo, você não precisa adicioná f=-lo à contagem de bytes (e no TIO você pode colocá-lo no cabeçalho), e é por isso que a @Quintec afirmou que é 139 bytes em vez de 141 bytes. Além disso, você pode mudar if((d.getDay()+1)%7>1)n++;para n+=-~d.getDay()%7>1;a golf-lo para 133 bytes .
Kevin Cruijssen 01/10/1918
1
Aqui, a dica relevante por que -~ié a mesma.(i+1) Além disso, se você ainda não o viu, pode ser interessante ler dicas de golfe em JavaScript e dicas de golfe em <todos os idiomas> . :)
Kevin Cruijssen 01/10/1918
1
A few more tips for future reference.
Shaggy
3

Python3 & Numpy, 96 bytes

I couldn't get smaller than the boring pre-made solution...

from numpy import*
d=datetime64
lambda s:busday_count(d('today'),d(f'{s[6:]}-{s[3:5]}-{s[:2]}'))

Try it online!

Aaron
fonte
Must get into Python 3 ;)
ElPedro
Based on your import, you are not using Python 3, but rather Python 3 with numpy.
Jonathan Frech
@JonathanFrech should that be in the title? others using python also have used a library as python has no builtin datatype for dates or times.
Aaron
1
This depends on your definition of builtin -- modules like datetime are standard library modules and thus I would count them as being part of the core language. However, when one uses third-party modules like numpy, one enhances the language's capabilities and therefore I would see it as another language.
Jonathan Frech
2

PowerShell, 107 99 bytes

-8 bytes thanks to mazzy

$d,$m,$y=$args-split'\.';for($a=date;$a-lt(date "$y-$m-$d");$a=$a|% *ys 1){$o+=($a|% D*k)-in1..5}$o

Try it online!

Performs a regex -split on the input $args, stores the values into $days, $months, and $years, respectively. Then, enters a for loop, initializing $a to today's date. The loop continues while $a is -lessthan our input target date. Each iteration we're adding 1 days to $a, and checking whether the current D*k (short for DayOfWeek) is in the range 1..5 (i.e., Monday to Friday). That Boolean result is accumulated into $o and once we're out of the loop that value is left on the pipeline and output is implicit.

AdmBorkBork
fonte
100 bytes? $d,$m,$y=$args-split'\.';for($a=date;$a-lt(date "$y-$m-$d");$a=$a|% *ys 1){$o+=($a|% D*k)-in1..5};$o
mazzy
1
@mazzy Indeed. Plus, the semicolon between for(...){...} and $o can be removed, so we're now below 100!
AdmBorkBork
2

Python 2, 147 143 141 140 bytes

from datetime import*
lambda e,s=date.today():sum((s+timedelta(x+1)).weekday()<5for x in range((date(*map(int,e.split(".")[::-1]))-s).days))

Try it online!

Takes a string, e, which represents the end date in the format "dd.MM.YYYY". Optionally also takes the start date, but this is expected to be a datetime.date.

The start date, s, is defaulted to today's date as a datetime.date object in order to disregard time. The end time is parsed into a datetime.datetime object then converted to a date, since datetime.date objects do not have a parse method and datetimes cannot be added to/subtracted from dates. Iterates through every day in (start, end] and adds 1 to the total if its weekday number is < 5. ([0-4] are [Mon-Fri], [5-6] are [Sat-Sun]).

Datetime parsing is the worst, you guys.

EDIT: Stole ElPedro's map(int,thing) trick to save 4 bytes.

EDIT 2: ELECTRIC BOOGALOO: Saved 2 bytes by making it an anonymous function. (Thanks Aaron!)

EDIT 3: xrange -> range. (Thanks again Aaron!)

Triggernometry
fonte
1
You're welcome! Nice answer :)
ElPedro
1
It is convention you can leave off the f= from lambda expressions here
Aaron
1
"Datetime parsing is the worst, you guys" Hahahaha feel my pain, you succeeded where I failed though :P
Quintec
@Aaron I'm never sure if that's okay with multiple functions or with import statements, thanks!
Triggernometry
1
You can also use range rather than xrange it should still work just fine.
Aaron
2

PHP, 66 bytes

for($t=time();$t<strtotime($argn);)$r+=date(N,$t+=86400)<6;echo$r;

empty output for 0; insert + between echo and $r to fix.

Run as pipe with -nr or try it online.


60 bytes with unary output:

for($t=time();$t<strtotime($argn);)echo date(N,$t+=86400)<6;
Titus
fonte
1

PHP (with Carbon), 107 bytes

function a($d){return Carbon\Carbon::parse($d)->diffInDaysFiltered(function($e){return!$e->isWeekend();});}
Daniel
fonte
1

IBM/Lotus Notes Formula - 99 bytes

d:=i;c:=0;@While(d>@Today;@Set("c";c+@If(@Weekday(d)=1:7;0;1));@Set("d";@Adjust(d;0;0;-1;0;0;0)));c

Takes input from a date/time field i. The input format of i is set to . separated so there is no need to convert the input. Notes can take a date input with any separator as long as you tell it before what it is going to be (hope that's not cheating!). Formula is in computed numeric field o on the same form.

Interesting aside: Ever since @For and @While were introduced into the Formula language in (I think) R6 by the great Damien Katz the only use I have found for them is code golfing. I have never used them in a production app.

There is no TIO available for formula so here is a screenshot taken on 02.10.2018:

enter image description here

ElPedro
fonte
1

Ruby, 81 bytes

->e{require'date';(Date.today...Date.strptime(e,'%d.%m.%Y')).count{|d|6>d.cwday}}

Try it online!

Idva
fonte
1

K4, 40 bytes

Solution:

{+/1<.q.mod[d+!(."."/:|"."\:x)-d:.z.d]7}

Explanation:

Calculate the difference between the dates, use modulo 7 to ignore weekends, sum up.

{+/1<.q.mod[d+!(."."/:|"."\:x)-d:.z.d]7} / the solution
     .q.mod[                         ]7  / modulo with 7
                                 .z.d    / UTC date
                               d:        / save as d
                              -          / subtract from
               (             )           / do this together
                       "."\:x            / split input on "."
                      |                  / reverse
                 "."/:                   / join back with "."
                .                        / take the value
              !                          / range 0..the difference
            d+                           / add today's date to range
   1<                                    / is 1 less than the modulo (ie is this mon-fri)?
 +/                                      / sum up

Notes:

  • same byte alternative to the date parsing: "D"$,/|"."\:x
streetster
fonte
1

C (clang), 209 208 205 bytes

Compiler flags -DU=u=localtime(&b) -DW=tm_wday -DY=tm_year -DT=tm_yday (52 bytes).

#import<time.h>
i;f(char*a){long b;struct tm t,*u;time(&b);U;strptime(a,"%d.%m.%Y",&t);for(i=0;u->T^t.T|u->Y^t.Y;u->W&&u->W^6&&i++,b+=86400,U);return i;}

Try it online!

-1 byte thanks to @JonathanFrech

Logern
fonte
?i++:0 -> &&++i.
Jonathan Frech
0

q, 52 79 bytes

{x:"D"$"."sv reverse"."vs x;i:0;while[x-.z.d;$[2>x mod 7;x-:1;[i+:1;x-:1]]];:i}

in q, each date has an underlying integer value, based on how many days have passed since the start of the millenium. Applying 'mod 7' to this, you get unique values for each day of the week (0 for Saturday, 6 for Friday). So when 2 > x mod 7, don't increment the counter, to avoid counting weekends.

EDIT: Missed strict date format, editing

EDIT2: Included

Thaufeki
fonte
1
Best I've come up with is {sum 1<mod[d+til("D"$x 10 vs 67893401)-d:.z.d]7} for 48 bytes without resorting to K verbs.
streetster
Using the list indices is a lot more elegant than reverse, and rather than using a loop, applying mod to the list. Great answer +1
Thaufeki