[C#] Using Classes and Objects - 5 задача


8

Условие: Write a method that calculates the number of workdays between today and given date, passed as parameter. Consider that workdays are all days from Monday to Friday except a fixed list of public holidays specified preliminary as array.

Решениеsource.
 
Обяснение: Вече сме решавали подобна задача (source). Тук само трябва да махнем почивните дни в началото и края на диапазона за да се получат точни интервали. След това го разделяме на седмици с 5 работни дни и махаме празниците, ако са в работни дни.



Отговори



22

Решение:

http://pastebin.com/qtMhAUSD

Обяснение:

1. Началната дата взимам чрез DateTime.Today;

2. Крайната дата взимам по следния начин: Приемам от козолата string в формат YYYY/MM/DD който споле разделям със .Split(' / ') и записва в string масив. След това си създавам int променлива за дните, месеците и годините и с помащата на тях създавам обект DateTime с крайната дата приета от конзолата.

3. Чрез: timeLen = (endDay - startDay).Days; взимам периода между двете дати.

4. Почивните дни пазя в масив от DateTime обекти ( почивните дни не са верни, просто тествах :) )

5. Първия цикъл върти от 0 до timeLen с цел да минем през всички дати и с startDay = startDay.AddDays(1) добавям по един ден към началната дата приближавайки я до крайанта.

6. Първата If проверка е за това дали деня е почивен (събота или недля)

7. Втория for цикъл обикаля по почивните дни в масива holidays и сравнява с текущата дата - ако има съвпадение присвояваме на bool променливата isHoliday - true.

8. Увеличваме броя на работните дни с 1 само ако isHoliday е false и след това я ресетваме на false.

Допълнителна информация:

DateTime

DateTime - MSDN

 


Благодарности на Ilia Penev ! Метнах една корекция за да работи когато началния ден е след крайния :)

 


от Teodor92 (13062 точки)


0
DateTime.Parse би ти спестило ръчното създаване на крайната дата.


0
Яко, не бях видял че имам такъв метод ! Мерси :)

от Teodor92 (13062 точки)



1

http://git.io/WqsQAg

Годините за празниците се увеличават и на всяка променлива от масива с празниците се придава нова стойност, която е с новата година. По-добър вариант не измислих. Тънък момент беше проверката дали празникът не е в събота или неделя, за да не се извади два пъти. 

DateTime вече ми е най-умразния клас... толкова пипкава задача и толкова google-ване за всяко нещо по тоя DateTime...


от georgiwe (720 точки)


1

Код:
http://pastebin.com/VjKrQRUw

Предимства на моето решение:
- рисува календар.
- проверява внимателно входа от конзолата и не гърми.

Недостатъци на моето решение:
-бавно е

Обяснение:
1 - взимам днешния ден и го запазвам в променлива 'today'

2 - чрез метода 'InputDate()' приемам данни за датата и ги проверявам. Запазвам ги в int[] с 3 позиции. После
 DateTime inputDay = new DateTime(arr[0], arr[1], arr[2]);
Изискванията за формата на числата са както следва:
- годината да не е от повече от 4 символа.
- годината да е число което може да се парсне.
- годината да не е по-малка от текущата година.
- ако годината е с над 100 години по-голяма от текущата година се изисква потвърждение че написаното число е нарочно, а не случайно (понеже програмата ще е бавна).
- Месеца и деня да не са с по повече от 2 символа.
- месеца и деня да могат да се парснат
- месеца да е в интервала 1-12
- деня да е в интервала 1-31
Не се налага да проверявам дали самата дата е преди текущата дата, защото ако това е вярно резултата просто ще е 0 и ще си е напълно верен. Въпреки това проверявам годината, защото така ще спестя излишното рестартиране на програмата за тези които пишат невнимателно и правят грешки от бързане.

3 - създавам  List<DateTime> hollydays, където добавям няколко празника.

4 - завъртам следния цикъл:
for (DateTime day = today; day.CompareTo(inputDay) <= 0; day = day.AddHours(24))
където вместо int използвам Datetime.
.CompareTo() връща -1, когато този преди точката е по-малък от този в скобите, 0 когато са равни и 1 когато този в скобите е по-малък.
.AddHours(24) е същото като .AddDays(1). Може би е с няколко мига по-бавно...

5 - Във всяко завъртане на цикъла проверявам дали дадения ден е събота или неделя.
Ако не е, тогава проверявам дали пък не е някой от официалните празници.

6 -  Във всяко завъртане на цикъла изписвам деня от седмицата и срещу него - работен ли е, или не. Форматирам изхода така че да е лесно четим.

7 - На всяко завъртане проверявам дали денят е неделя. Ако е неделя, тогава заделям няколко реда в които да дам информация за следващата седмица, така че да се знае за коя седмица става дума.

8 - Накрая принтирам броя на работните дни.


от lokiko91 (790 точки)


0

Ето тук има и библиотека за празниците и подобни: http://commonlibrarynet.codeplex.com

Казва се HolidayCalendar


от victor.velchev (1225 точки)


1

http://pastebin.com/JeB1CxCT

Ще съм благодарен ако някой може да ми каже къде бъркам... 


от llhewitt (0 точки)


0
if (date.Date.CompareTo(holidays) == 0)
{
count--; <- това ти е проблема Ако брои дните от понеделник до петък и сряда е празник става следното Понеделник -> един ден Вторник -> два дни Сряда -> един ден Четвъртък -> два дни Петък -> три дни
Не трябва да вадиш при празник, а просто да не правиш нищо

от wnvko (3123 точки)

0
да това е едно на ръка, но накрая като стартирам програмата и ми дава SystemArgumentException и ми казва, че if (date.Date.CompareTo(holidays) == 0) тука object-a трябва да е от тип DateTime, а той е такъв

от llhewitt (0 точки)



2

Едно решение и от мен - http://pastebin.com/z61kZVsw

Работи за дата напред и назад, както и за различни години. Не е прекалено тествано, така че всякакви бъгове са добре дошли :)


от Sir_EFO (733 точки)


0
Решението ти работи доста добре, както назад във времето, така и напред. Прегледах доста решения и твоето е най-добро за сега.

от SystemeX (5 точки)


0
http://pastebin.com/Ku9UEfgD
Това е моето решение. Малко дълго стана, но уж работи :) Включени са официалните почивни дни (тези, които се отработват не са включени понеже се елиминират), както и почивните дни за Великден (изчисляват се за всяка година). Приемам всякакви идеи и критики :)

от Gornakov (10 точки)


0

https://gist.github.com/Ob1To/8411764

Това е от мен - > Правя си counter който е равен на крайната дата , която ни дава user-а минус сегашната дата . Така получавам дните като int (int counter = (endDay - today).Days;) - докато измъдря как да върне по тоя начин инт ми отне известно време. После си правя масив за почивните дни . Накрая while цикъл в който вадя от counter-а единичка ако е почивен , else ако е holiday и добавям 1 ден към текущият ... така когато станат равен today == endDay край на while-a и печатам counter


от Ob1To (40 точки)


0
http://pastebin.com/F9Ap9Z5R Моето решение с фор-цикЪли

от kskondov (50 точки)