İş Günü Geri Sayımı


17

İş hayatını kolaylaştırmak için dahi bir fikrim vardı - sadece iş günlerini sayan belirli bir tarihe geri sayım.


Temel görev, yalnızca geri sayımdaki iş günlerini içeren belirli bir tarihe geri sayım oluşturmaktır.

İş günü Pazartesi , Salı , Çarşamba , Perşembe ve Cuma günleri sayılır .

Girdi , "gayri resmi" Avrupa standart formatında belirli bir tarih dd.MM.yyyyolmalı ve bugün ya da gelecekte bir gün olmalıdır.

Çıktı yalnızca kalan gün sayısı olmalıdır.

'S gibi kısa kod kazanır.


Test durumu:

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

Sorudaki birkaç şeyi kaçırırsam, lütfen beni affet - bu benim ilk sorum :)

DÜZENLE:

  • <-false yerine çıktı olarak kullanabilirsiniz , 0 ancak güzel değil
  • DST'ye saygı duymaya gerek yok

9
Bu "gayri resmi" Avrupa girdi biçiminin arkasında belirli bir neden var mı ? Fikir birliğimiz mümkün olduğunda esnek girişe izin vermektir.
Arnauld

6
İşlenmesi zor bir tarih biçiminin "ekstra zorluğunu" eklemenin gerçekten bir anlamı var mı? Bu sadece esnek tarih formatlarına sahip haksız wrt dilleri gibi görünüyor ...
Quintec

3
@Hille Ben "zor" olduğunu söylemedim, sadece gereksiz bir güçlük, özellikle kod-golf ... Arnauld yukarıda yayınlanan bağlantı not edin ... genellikle esnek giriş norm ...
Quintec

6
Bu arada, bunun ilk zorluğunuz olduğunu belirtiyorsunuz; Sana kullanmaya davet Sandbox ana kadar bir meydan okuma göndermeden önce arıtma için! Aksi takdirde, iyi iş çıkardınız ve sizden daha fazlasını görmekten keyif alacağım!
Giuseppe

7
Katı girdi biçiminden gerçekten etkilenmemiş ama bunun dışında iyi bir meydan okuma.
ElPedro

Yanıtlar:


18

05AB1E , 130 128 133 131 124 123 bayt

ž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#

Aklımı kaçırdım..

05AB1E golf dili için girişin .veya ile olması önemli değildir -. Ancak, 05AB1E'de Date nesneleri veya hesaplamaları için herhangi bir yerleşik yoktur. Tarihi ile ilgili tek yerleşik bugünün yıl / ay / gün / saat / dakika / saniye / mikrosaniyedir.

Bu nedenle, gördüğünüz kodun neredeyse tamamı ertesi güne gitmek için manuel hesaplamalar ve haftanın gününü hesaplamaktır.

Zeller formülünde unuttuğum bir kısım nedeniyle +5 bayt (Ocak ve Şubat ayları için yıl-1).

Çevrimiçi deneyin veya kendi belirlediğiniz 'bugün' tarihiyle çevrimiçi deneyin .

Açıklama:

Metin gelen duvar.

Genel olarak, kod aşağıdaki sözde kodu izler:

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;05AB1E programının bu kısmıdır:

ž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;ve 3) Start an infinite loop:05AB1E programında basittir:

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

4) If(currentDate is NOT a Saturday and currentDate is NOT a Sunday):manuel hesaplamalar ile ilk zor kısmıdır. 05AB1E'de Tarih yerleşikleri bulunmadığından Haftanın Gününü manuel olarak hesaplamamız gerekir.

Bunu yapmak için genel formül:

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

Mart-Aralık ayları için:

  • q iseday (ay[1, 31])
  • m , 1 endekslimonth ([3, 12]) 'dir
  • K yüzyılın yılıdır (yearmod100 )
  • J , 0 indeksli yüzyıldır (year100)

Ocak ve Şubat ayları için:

  • q iseday (ay[1, 31])
  • m , 1 endekslimonth+12 ([13, 14])
  • K , bir önceki yıl için yüzyılın yılıdır ((year1)mod100 )
  • J , bir önceki yıl için 0 endeksli yüzyıldır (year1100)

Sonuç olarak h haftasında , 0 = Cumartesi, 1 = Pazar, ..., 6 = Cuma.
Kaynak: Zeller'in uyumu

Bunu 05AB1E programının bu bölümünde görebiliriz:

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;tekrar düz ileri:

     # 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 lineyine daha karmaşıktır, çünkü manuel olarak yapmak zorundayız. Yani bu aşağıdaki sözde koda genişletilecek:

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;

Kaynaklar:
Bir yılın artık yıl olup olmadığını belirleme algoritması. (DÜZENLEME: Artık alakalı değil, çünkü 7 bayt tasarruf sağlayan artık yılları kontrol etmek için alternatif bir yöntem kullanıyorum .)
Bir aydaki gün sayısını belirlemek için algoritma.

6a) Integer isLeapYear = ...;05AB1E programında şu şekilde yapılır:

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`

Ayrıca bu 05AB1E cevabımda da kullanıldı, bu nedenle adımları örneklemek için birkaç örnek yıl eklendi.

6b) currentDate.month == 2 ?ve 6c) 28 + isLeapYearşu şekilde yapılır:

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) :ve 6e) 31 - (currentDate.month - 1) % 7 % 2;şu şekilde yapılır:

ë           # 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):şu şekilde yapılır:

     # 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;şu şekilde yapılır:

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:ve 6i) nextDate.day = 1;daha sonra şu şekilde yapılır:

ë        # 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;ve 6n) nextDate.year += 1;daha sonra şu şekilde yapılır:

ë        # 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

Ve son olarak 8) If(currentDate == parsed input-string):ve 9) 'da 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)

5
Sen bir delisin ... upvote var.
AdmBorkBork

1
En uzun 05AB1E programı?
Luis Mendo

2
@LuisMendo Kapat, ama korkarım kendime bir 05AB1E daha uzun ve daha çok yaklaşan bir cevap var .. ;) Eminim burada birkaç bayt golf ve basitleştirmek mümkün olacak ertesi gün sözde kod uygulamasının bölümleri. Yarın sabah bakacak, ama sadece spordan döndü ve yakında yatağa gidecek.
Kevin Cruijssen

11

Excel 24 Bayt

A1 hücresine girdi olduğunu varsayar

=NETWORKDAYS(NOW()+1,A1)

Yerleşik işlevi kullanır. Ne yazık ki işlev hem bugün hem de bitiş tarihini içeriyor. O günden beri bugün sayılmayacağı açıklandı, bu yüzden bugün saymamak için ŞİMDİ bir tane ekliyorum.

Sayı biçimiyle ilgili yorumları ele almak için yine Excel standardı budur: enter image description here


Bu, tarih değerleri ile çalışırken, belirtildiği gibi girdi alamaz. Yani (en azından ABD versiyonunda) 10.12.2018, bir tarih yerine bir hücrede tutulduğunda bir dizedir. Bunu düzeltmek için bariz ancak uzun bir çözüm değiştirmektir A1için DATE(RIGHT(A1,4),MID(A1,4,2),LEFT(A1,2)), çözümde
Taylor Scott

maalesef, topluluk geçerli olması için dillerin varsayılan ayarları altında çalıştırılması gerektiğine karar verdi (bununla ilgili gördüğüm tek istisna dil - IE, eğer diliniz hem İngilizce hem de İspanyolca'yı destekliyorsa, her ikisini de kullanabilirsiniz, ancak Bu not edilmelidir.) Dahası, OP (@hille) formatın esnek olduğunu ve aslında tam tersini belirtti (bu soruya ikinci yoruma bakınız)
Taylor Scott

2
Biçim standart değil , yerel ayar tabanlı. Excel biçimi HKCU\Control Panel\International\sDecimalkayıt defteri dizesinden okur . MM / dd / yyyy olan varsayılan bir ABD Windows kurulumunda. Çoğu AB ülkesinde bu varsayılan değerdir.
Erik A

@luisMendo Evet, işe yarıyor. Herhangi bir açıklama görmedim. Bunun yerine geçen gün sayılmasaydı, = AĞ GÜNLERİ (ŞİMDİ (), A1-1) alabilirdim. Hangi açıklama olursa olsun her zaman aynı bayt sayısı olacağını biliyordum.
Keeta - Monica'yı

Memnun oldum. Downvote'u kaldırdım
Luis Mendo


8

Java 10, 233 232 226 bayt

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;}

Tarih her zaman bana Java'nın ne kadar ayrıntılı olduğunu hatırlatıyor ..

NOT: İki kısa Java (175 bayt altında) cevaplar, şimdi vardır önceki Java sürümlerinden kaldırılmış yöntemlerin akıllı kullanımı ile bir tarafından @LukeStevens ve kullanan bir java.time.LocalDateJava 8 yana yeni olduğunu tarafından @ OlivierGrégoire .

Çevrimiçi deneyin.

Açıklama:

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

Yapabilir misin e=s.clone()?
Quintec

1
Biz de yapabiliriz ( Calendar s=Calendar.getInstance(),e=s.getInstance()maalesef ) , ne yazık ki tam olarak aynı uzunlukta olur.
Misha Lavrov

1
@MishaLavrov Ah, statik Cgerçekten gerekli değil. CBaşka bir yerde de kullandığım kodun eski bir parçasıydı . var s=Calendar.getInstance();var e=s.getInstance();Çok teşekkürler kullanarak 1 bayt golf başardık . :)
Kevin Cruijssen

1
150 bayt kullanarak java.time.
Olivier Grégoire

1
Bitti! Diğer cevaba bayt olarak çok yakın, ama henüz yenmedi.
Olivier Grégoire

7

JavaScript (ES6), 116 103 bayt

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

Çevrimiçi deneyin!

Nasıl?

JavaScript zaman damgası, UNIX döneminden bu yana geçen milisaniye sayısı olarak tanımlanır . Geçerli zaman damgası değişkente tutulurn.

Her yinelemede, n bir tarih oluşturmak D(JavaScript nesnesi olarak). Bu tarih, yöntemle ISO 8601 biçimine dönüştürülür .toJSON():

YYYY - AA - GG T ss : dd : ss.sss Z

Bu dize ile başladığından YYYY-MM-DD, benzer bir biçimde başka bir dize ile sözlüksel karşılaştırma yapmak güvenlidir. Bu yüzden girdi dizesini dönüştürmek istiyoruzdiçin YYYY-MM-DDyerine girdi dizesi biçimine bizim bilgisayarlı tarih dönüştürme DD.MM.YYYY(ki leksikografik sıralanabilir olamaz):

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

Her özyinelemeli çağrıdan önce D.getDay(), hiçbiri yoksa nihai sonucu artırırız0 (Pazar) ne 6 (Cumartesi), yani uygun değilse 0 modülo 6:

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

Ekleriz 86,400,000 milisaniye n Ertesi güne ulaşmak için.


6

MATL , 24 bayt

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

Çevrimiçi deneyin!

Belirli bir kod golf dilinin büyük bir avantajı olması için herhangi bir giriş formatına sahip olmak istemiyorum

Yarısını başardın :-)

açıklama

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

Zorluğu doğru anladıysam, yalnızca bir tarih girdisi alıp bugünün tarihiyle karşılaştırırsınız. Örneğin, 16.10.2018bugün (Pazartesi 01-10-2018) 11yarın 10, vb.
İle sonuçlanır mı?

@KevinCruijssen Teşekkürler! Şimdi düzeltildi
Luis Mendo

1
Ve aynı bayt sayısıyla. :) Güzel, benden +1.
Kevin Cruijssen

6

Wolfram Dili (Mathematica) , 64 56 bayt

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

Çevrimiçi deneyin!

DayCount[x,y,"Weekday"]arasında hafta içi sayısını sayar xve y.

Girdiler xve döndürülen gibi ybir fantezi veya biçiminde bir dize (ne yazık ki) dahil olmak üzere birçok şey olabilirDateObjectTodaymm.dd.yyyy .

Önceki girişimim Mathematica'ya nasıl ayrıştırılacağını söyleyerek dd.mm.yyyygirdiyi bir haline dönüştürmeye çalıştı DateObject; yeni çözüm, Mathematica'nın beklediği sırayla gün ve ayı koymak için dizeyi yeniden düzenler.

28 baytlık çözüm belirterek It yetmeyecek DayCount[Today,#,"Weekday"]&sadece ayrıca doğru bir ay-gün-yıl giriş formatı için mükemmel çalışıyor, ancak kolları açık gibi gün-ay-yıl girişler 31.12.2018, hangi olabilir 31 olasılıkla ortalama değil "12.gün ay". Bu yüzden zamanın% 60'ından fazlası doğrudur :)



5

R, 72 chars

A variation on the answer provided by @ngm which avoids the grepl to save a few characters and works in non-English locales.

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


1
Shorter and more general too. Nice answer and welcome to the asylum.
ngm

1
Welcome to PPCG! you can add a TIO link - it's easy and formats the answer for you :)
JayCe

5

Java (OpenJDK 8), 174 166 165 bytes

With a bit of inspiration from Kevin's answer and a good ol' trawl through the deprecated Date API, I've managed to get a more succinct Java solution.

-8 bytes thanks to Kevin's inventive regex date parsing

-1 bytes thanks to Nevay's clever bitwise operation

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;}

Try it online!

Explanation

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

1
Nice answer! Smart use of the varargs with the d=d[0].split and the deprecated .parse with default format MM/dd/yyyy format. One small mistake in your post, you have import java.text.*; instead of import java.util.*; in your code, and // Required import for both Calendar and Date in your explanation (even though you don't use Calendar).
Kevin Cruijssen

@KevinCruijssen No idea why I had java.text but fixed now! Thanks!
Luke Stevens

1
Although I liked the d=d[0].split with the varargs, changing the input to a regular String, removing d=d[0].split("\\."); and changing d[1]+"/"+d[0]+"/"+d[2] to d.replaceAll("(..).(..).","$2/$1/") saves 7 bytes.
Kevin Cruijssen

1
And 1 more byte by changing r+=new Date(s).getDay()%6<1?0:1,s+=864e5); to 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

Red, 72 bytes

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

Try it online!

Takes the date in format dd-mm-yyyy, for example 31-10-2018 (also works with 10-Oct-2018)

Strict input:

Red, 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]

Try it online!

Bonus:

Returns a list of the dates/weekdays of the working days up to the given date:

Red, 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
        ]
    ]
]

Try it online!


Agh, no fair, in python I need to spend about 72 bytes processing this IO format... :P
Quintec

1
Usually my Red solutions are among the longest ones, but fortunately Red deals very well with dates :)
Galen Ivanov

1
90 bytes to process python... i'm done, I quit until there's a more flexible input format :P
Quintec


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*

Try it online!

-7 with thanks to @mypetlion

-7 more with thanks to @ovs

+30 due to the very restrictive input format which I only noticed just before I posted my previous code which took input as e.g. (2018,11,1) :-(


2
No need for this: (0,1)[t.weekday()<5]. Python booleans are a subclass of int and True, False can be used in arithmetic operations as 1,0. Replace it with c+=t.weekday()<5 to save 7 bytes.
mypetlion

1
149 bytes as a lambda.
ovs

Thanks @mypetlion. I shouldn't have missed that one.
ElPedro

Thanks @ovs. Second time you have helped recently. Last time was a very impressive -30. Was trying to work out how to get this into a lambda.
ElPedro

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;}

Try it online!

Credits


1
You can change the (.*)\\.(.*)\\.(.*) to (..).(..).(.*).
Kevin Cruijssen

With your replaceAll technique his answer can be golfed by 7 bytes as well however, so yours is still slightly longer. ;)
Kevin Cruijssen

@KevinCruijssen Thanks for the regex! And no worries: I don't mind having a longer answer ;)
Olivier Grégoire

3

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

35 bytes less thanks to Quintec and 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;}

Try it 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
}

1
158 bytes with lambda
Quintec

1
139 bytes with improved if condition
Quintec

1
Since your method isn't recursive, you don't need to add the f= to the byte-count (and on TIO you can put it in the header), which is why @Quintec stated it's 139 bytes instead of 141 bytes. In addition, you can change if((d.getDay()+1)%7>1)n++; to n+=-~d.getDay()%7>1; to golf it to 133 bytes.
Kevin Cruijssen

1
Here the relevant tip why -~i is the same as (i+1) Also, if you haven't seen it yet, Tips for golfing in JavaScript and Tips for golfing in <all languages> might be interesting to read through. :)
Kevin Cruijssen

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!


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.


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


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;

1

PHP (with Carbon), 107 bytes

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

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



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

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


?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


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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.