Mam scenariusz, gdzie daną datę (DateTime
), data plus/minus x
dni (uzyskiwana z DateTime.AddDays
) należy dodać lub odjąć x
dni robocze, tj pominąć weekendy i święta. Jak mogę to zrobić? Czy powinienem wdrożyć własną wersję i dołączyć ją do kalendarza czy coś takiego?C# DateTime do Dodaj/odejmij Dni Roboczych
Odpowiedz
Sugerowałbym, że trzeba wprowadzić je w swój własny, i zrobi to wewnątrz metodę rozszerzenia jak ten:
public static class DateTimeExtensions
{
public static DateTime AddWorkdays(this DateTime originalDate, int workDays)
{
DateTime tmpDate = originalDate;
while (workDays > 0)
{
tmpDate = tmpDate.AddDays(1);
if (tmpDate.DayOfWeek < DayOfWeek.Saturday &&
tmpDate.DayOfWeek > DayOfWeek.Sunday &&
!tmpDate.IsHoliday())
workDays--;
}
return tmpDate;
}
public static bool IsHoliday(this DateTime originalDate)
{
// INSERT YOUR HOlIDAY-CODE HERE!
return false;
}
}
Ten kod zgłasza wyjątek 'ArgumentOutOfRangeException'. Również nie obsługuje negatywnych dni. – Kev
Tak, wiem o tym. Ten kod pokazuje jedynie niegrzeczną koncepcję i musi być implementowany bardziej wyrafinowany. Myślę, że są gotowe do użycia biblioteki na codepleksie. – sprinter252
Należy sprawdzić, czy dzień pracuje sam, ponieważ klasa DateTime nie może wiedzieć, które dni będą ferie w tym roku :)
powinny Prawdopodobnie masz baza wakacji do sprawdzenia przed, a jeżeli wartość dzień plus/minus x jest równy wartości w bazie danych dodaj/odejmij inny, ponieważ nie każdy ma takie same święta.
public static class DateTimeExtensions
{
public static DateTime AddWorkDays(this DateTime date, int workingDays)
{
int direction = workingDays < 0 ? -1 : 1;
DateTime newDate = date;
while (workingDays != 0)
{
newDate = newDate.AddDays(direction);
if (newDate.DayOfWeek != DayOfWeek.Saturday &&
newDate.DayOfWeek != DayOfWeek.Sunday &&
!newDate.IsHoliday())
{
workingDays -= direction;
}
}
return newDate;
}
public static bool IsHoliday(this DateTime date)
{
// You'd load/cache from a DB or file somewhere rather than hardcode
DateTime[] holidays =
new DateTime[] {
new DateTime(2010,12,27),
new DateTime(2010,12,28),
new DateTime(2011,01,03),
new DateTime(2011,01,12),
new DateTime(2011,01,13)
};
return holidays.Contains(date.Date);
}
}
Zrobiłem to ostatnio:
private DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays, ICollection<DateTime> holidays)
{
var futureDate = fromDate;
var daterange = Enumerable.Range(1, numberofWorkDays * 2);
var dateSet = daterange.Select (d => futureDate.AddDays(d));
var dateSetElim = dateSet.Except(holidays).Except(dateSet.Where(s =>s.DayOfWeek == DayOfWeek.Sunday).Except(dateSet.Where (s=>s.DayOfWeek==DayOfWeek.Saturday)));
//zero-based array
futureDate = dateSetElim.ElementAt(numberofWorkDays-1);
return futureDate;
}
Musisz sprawdzić zachowanie przez całe życie, tylko je dodam!
Zajęło mi trochę czasu, aby to rozwiązać ... Stworzyłem tabelę DB, którą wciągam do tablicy z dniami świątecznymi. All Credit to Kev (on this post) .. Musiałem zmodyfikować jego pracę tak, jak jest dla mnie.
W moim przypadku, jeśli pierwszy dzień był sobotą, a moja workingDayCount = -1, chcę odejść w czwartek (ponieważ moja randka nie może przypadać na weekend lub na wakacje ... musi to być dzień roboczy .. w tym przypadku piątek.)
Kod Kev może odejść w niedzielę ... poniższy kod przeniesie go do poprzedniego dnia roboczego (zazwyczaj w piątek - chyba że piątek jest świętem, kiedy minie czwartek).
public static DateTime AddWorkDays(this DateTime date, int workingDays, params Holidays[] bankHolidays)
{
int direction = workingDays < 0 ? -1 : 1;
DateTime newDate = date;
// If a working day count of Zero is passed, return the date passed
if (workingDays == 0)
{
newDate = date;
}
else
{
while (workingDays != -direction)
{
if (newDate.DayOfWeek != DayOfWeek.Saturday &&
newDate.DayOfWeek != DayOfWeek.Sunday &&
Array.IndexOf(bankHolidays, newDate) < 0)
{
workingDays -= direction;
}
// if the original return date falls on a weekend or holiday, this will take it to the previous/next workday, but the "if" statement keeps it from going a day too far.
if (workingDays != -direction)
{ newDate = newDate.AddDays(direction); }
}
}
return newDate;
}
Oto mój prosty klasa Urlop:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Clarity.Utilities
{
public class Holidays
{
public int Id { get; set; }
public DateTime dtHoliday { get; set; }
public string Desc { get; set; }
public bool Active { get; set; }
}
}
Oto jak wypełnić tablicę:
private Holidays[] PopulateArrayWithDates()
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DBConn"].ConnectionString);
DateTime[] dtHolidays = new DateTime[] { };
string sql = @"SELECT HolDate, HolName FROM [Server].DBName.dbo.tblHolidays";
SqlCommand ADDCmd = new SqlCommand(sql, con);
DataTable table = new DataTable();
DataTable tbl = new DataTable();
Utilities.Holidays[] allRecords = null;
using (var command = new SqlCommand(sql, con))
{
con.Open();
using (var reader = command.ExecuteReader())
{
var list = new List<Holidays>();
while (reader.Read())
list.Add(new Holidays { dtHoliday = reader.GetDateTime(0), Desc = reader.GetString(1) });
allRecords = list.ToArray();
}
}
return allRecords;
}
Mam zmodyfikowano dotychczasowe odpowiedzi podejść bardziej funkcjonalne. I dostarczyły dwa rozwiązania poniżej, jeden przy użyciu IEnumerable i jeden przy użyciu IObservable i biernej Rozszerzenia
Korzystanie IObservable
public static class DateTimeExtensions
{
public static DateTime AddWorkDays(this DateTime date, int workingDays)
{
return Observable
.Generate
(date, arg => true, arg => arg.AddDays(workingDays < 0 ? -1 : 1), arg => arg)
.Where(newDate =>
(newDate.DayOfWeek != DayOfWeek.Saturday &&
newDate.DayOfWeek != DayOfWeek.Sunday &&
!newDate.IsHoliday()))
.Take(Math.Abs(workingDays) + 1)
.LastAsync()
.Wait();
}
public static bool IsHoliday(this DateTime date)
{
return false;
}
}
Korzystanie IEnumerable
public static class DateTimeExtensions
{
public static DateTime AddWorkDays(this DateTime date, int workingDays)
{
return date.GetDates(workingDays < 0)
.Where(newDate =>
(newDate.DayOfWeek != DayOfWeek.Saturday &&
newDate.DayOfWeek != DayOfWeek.Sunday &&
!newDate.IsHoliday()))
.Take(Math.Abs(workingDays))
.Last();
}
private static IEnumerable<DateTime> GetDates(this DateTime date, bool isForward)
{
while (true)
{
date = date.AddDays(isForward ? -1 : 1);
yield return date;
}
}
public static bool IsHoliday(this DateTime date)
{
return false;
}
}
Szukałem dodawać i odejmować daty pomijanie weekendy i to jest pierwszy wpis w Google. Nie podoba ci się żaden z odpowiedzi tutaj więc dodam ten, zrobiłem sobie w przypadku gdy ktoś kończy się tutaj, jak ja:
public static DateTime AddExcludingWeekends(this DateTime dateTime, int nDays)
{
var wholeWeeks = nDays/5; //since nDays does not include weekdays every week is considered as 5 days
var absDays = Math.Abs(nDays);
var remaining = absDays % 5; //results in the number remaining days to add or substract excluding the whole weeks
var direction = nDays/absDays;//results in 1 if nDays is posisive or -1 if it's negative
while (dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday)
dateTime = dateTime.AddDays(direction); //If we are already in a weekend, get out of it
while (remaining-- > 0)
{//add remaining days...
dateTime = dateTime.AddDays(direction);
if (dateTime.DayOfWeek == DayOfWeek.Saturday)
dateTime = dateTime.AddDays(direction * 2);//...skipping weekends
}
return dateTime.AddDays(wholeWeeks * 7); //Finally add the whole weeks as 7 days, thus skipping the weekends without checking for DayOfWeek
}
Mam nadzieję, że ktoś pomaga.
Prostym rozwiązaniem jest tutaj Wypróbuj go i cieszyć się kodowanie
public class Program
{
public static void Main(string[] args)
{
Double days= 7;
string s=DateTime.Now.AddDays(7).ToString("dd/MM/yyyy");
DateTime dt= OrderDeliveryDate(days);
Console.WriteLine("dt"+dt.ToString("dd/MM/yyyy"));
}
public static DateTime OrderDeliveryDate(Double days)
{
Double count=0;
for(int i=0;i<days;i++)
{
if(DateTime.Now.AddDays(i).DayOfWeek.ToString() == "Saturday")
{
count= count+1;
}
else if(DateTime.Now.AddDays(i).DayOfWeek.ToString() == "Sunday")
{
count=count+1;
}
}
days=days+count;
return DateTime.Now.AddDays(days);
}
}
- 1. Dodawanie dni roboczych do kolumny datetime
- 2. Datetime w C# dodaj dni
- 3. Zliczanie regularnych dni roboczych w danym okresie czasu
- 4. Zliczanie dni roboczych między dwiema seriami
- 5. Julian dni od DateTime
- 6. Jak dodać dni robocze do NSDate tylko w dni robocze?
- 7. git log od wczoraj tylko dla dni roboczych
- 8. Panda liczba dni roboczych między DatetimeIndex a datownikiem
- 9. Jak ustawić alarm dla dni roboczych w android
- 10. Otrzymasz wartość datetime z X dni?
- 11. Jak obliczyć liczbę dni roboczych między dwiema datami?
- 12. Parsowanie datetime C# do javascript datetime
- 13. Jak dodać liczbę dni w postgresql datetime
- 14. C# DateTime do "YYYYMMDDHHMMSS" format
- 15. Konwertuj ciąg do Datetime C#
- 16. anonimowy dostęp do obszarów roboczych Jennkins
- 17. C++ DateTime klasa
- 18. C++ Konwersja łańcucha datetime do epoki Czyściutko
- 19. C++ znacznik czasu do czytelnej funkcji datetime
- 20. Konwersja czasu do DateTime w C#
- 21. Uzyskaj liczbę dni między dwoma różnymi obiektami DateTime
- 22. C#: zainicjować macierz DateTime
- 23. Rozmiary grup roboczych
- 24. Jak przekonwertować DateTime? do DateTime
- 25. Dodawanie dni do daty
- 26. Dodawanie dni do kalendarza
- 27. Dodawanie dni do NSDate
- 28. Obliczanie liczby dni między dwiema datami w C#
- 29. DateTime W języku C#
- 30. Tydzień Roku C# Datetime
Skąd wiesz, które dni są dniami? –
pozwala założyć, że mam te dane. – Aks
Możesz rozszerzyć metodę wskazaną przez @Taz, aby uwzględnić święta. –