С учетом даты (типа DateTime
), как найти третью пятницу в месяце этой даты?
Как найти третью пятницу в месяц с С#?
Ответ 1
Я не тестировал это, но поскольку третья пятница не может произойти до 15 числа месяца, создайте новую DateTime, а затем просто увеличивайте ее до пятницы.
DateTime thirdFriday= new DateTime(yourDate.Year, yourDate.Month, 15);
while (thirdFriday.DayOfWeek != DayOfWeek.Friday)
{
thirdFriday = thirdFriday.AddDays(1);
}
Ответ 2
Я собираюсь повторить свой ответ из здесь с одним небольшим дополнением.
Язык-агностическая версия:
Чтобы получить первый конкретный день месяца, начните с первого дня месяца: yyyy-mm-01. Используйте любую функцию, чтобы дать число, соответствующее дню недели; в С# это будет DateTime.DayOfWeek
. Вычтите это число с того дня, которое вы ищете; например, если первый день месяца - среда (3), и вы ищете пятницу (5), вычтите 3 из 5, оставив 2. Если ответ отрицательный, добавьте 7. Наконец добавьте это к первому из месяц; для моего примера, первая пятница будет третьей.
Чтобы попасть в последнюю пятницу месяца, найдите первую пятницу следующего месяца и вычтите 7 дней.
Чтобы получить третью пятницу месяца, добавьте 14 дней до первой пятницы.
Ответ 3
Я следовал за алгоритмом User: Mark Ransom и написал обобщенный дневной поиск. Например, чтобы получить третью пятницу декабря 2013 года,
int thirdFriday = DayFinder.FindDay(2013, 12, DayOfWeek.Friday, 3);
И вот определение функции. Он не имеет итерационных циклов, поэтому его эффективность.
public class DayFinder
{
//For example to find the day for 2nd Friday, February, 2016
//=>call FindDay(2016, 2, DayOfWeek.Friday, 2)
public static int FindDay(int year, int month, dayOfWeek Day, int occurance)
{
if (occurance <= 0 || occurance > 5)
throw new Exception("Occurance is invalid");
DateTime firstDayOfMonth = new DateTime(year, month, 1);
//Substract first day of the month with the required day of the week
var daysneeded = (int)day - (int)firstDayOfMonth.DayOfWeek;
//if it is less than zero we need to get the next week day (add 7 days)
if (daysneeded < 0) daysneeded = daysneeded + 7;
//DayOfWeek is zero index based; multiply by the Occurance to get the day
var resultedDay = (daysneeded + 1)+ (7*(occurance-1));
if(resultedDay > (firstDayOfMonth.AddMonths(1) - firstDayOfMonth).Days)
throw new Exception(String.Format("No {0} occurance(s) of {1} in the required month", occurance, day.ToString()));
return resultedDay;
}
}
Ответ 4
Немного оптимизированная версия:
DateTime Now = DateTime.Now;
DateTime TempDate = new DateTime(Now.Year, Now.Month, 1);
// find first friday
while (TempDate.DayOfWeek != DayOfWeek.Friday)
TempDate = TempDate.AddDays(1);
// add two weeks
TempDate = TempDate.AddDays(14);
Ответ 5
Наверное, лучше всего отнести это к методу, чтобы сделать комбинацию даты/дня:
(метод расширения)
public static bool TryGetDayOfMonth(this DateTime instance,
DayOfWeek dayOfWeek,
int occurance,
out DateTime dateOfMonth)
{
if (instance == null)
{
throw new ArgumentNullException("instance");
}
if (occurance <= 0 || occurance > 5)
{
throw new ArgumentOutOfRangeException("occurance", "Occurance must be greater than zero and less than 6.");
}
bool result;
dateOfMonth = new DateTime();
// Change to first day of the month
DateTime dayOfMonth = instance.AddDays(1 - instance.Day);
// Find first dayOfWeek of this month;
if (dayOfMonth.DayOfWeek > dayOfWeek)
{
dayOfMonth = dayOfMonth.AddDays(7 - (int)dayOfMonth.DayOfWeek + (int)dayOfWeek);
}
else
{
dayOfMonth = dayOfMonth.AddDays((int)dayOfWeek - (int)dayOfMonth.DayOfWeek);
}
// add 7 days per occurance
dayOfMonth = dayOfMonth.AddDays(7 * (occurance - 1));
// make sure this occurance is within the original month
result = dayOfMonth.Month == instance.Month;
if (result)
{
dateOfMonth = dayOfMonth;
}
return result;
}
Результаты:
DateTime myDate = new DateTime(2013, 1, 1)
DateTime dateOfMonth;
myDate.TryGetDayOfMonth(DayOfWeek.Sunday, 1, out dateOfMonth)
// returns: true; dateOfMonth = Sunday, 1/6/2013
myDate.TryGetDayOfMonth(DayOfWeek.Sunday, 4, out dateOfMonth)
// returns: true; dateOfMonth = Sunday, 1/27/2013
myDate.TryGetDayOfMonth(DayOfWeek.Sunday, 5, out dateOfMonth)
// returns: false;
myDate.TryGetDayOfMonth(DayOfWeek.Wednesday, 1, out dateOfMonth)
// returns: true; dateOfMonth = Wednesday, 1/2/2013
myDate.TryGetDayOfMonth(DayOfWeek.Wednesday, 4, out dateOfMonth)
// returns: true; dateOfMonth = Wednesday, 1/23/2013
myDate.TryGetDayOfMonth(DayOfWeek.Wednesday, 5, out dateOfMonth)
// returns: true; dateOfMonth = Wednesday, 1/30/2013
// etc
Ответ 6
Старый пост, но я нашел замечательно мало достойных ответов онлайн для этой, безусловно, довольно распространенной проблемы! Ответ на Mark Ransom должен быть последним словом в этом алгоритме, но вот класс-помощник С# (я ненавижу расширения) для всех, кто хочет быстро ответить на общие проблемы "первого дня недели в месяц", "xth day" недели за месяцем "и" последний день недели в месяц ".
Я изменил его, чтобы вернуть DateTime.MinValue
, если X-й день недели выпадает за указанный месяц, а не на следующий месяц, потому что это мне кажется более полезным.
Я также добавил в программу примера LINQPad-runnable.
void Main()
{
DayOfWeek dow = DayOfWeek.Friday;
int y = 2014;
int m = 2;
String.Format("First {0}: {1}", new object[] { dow, DateHelper.FirstDayOfWeekInMonth(y, m, dow) }).Dump();
"".Dump();
String.Format("Last {0}: {1}", new object[] { dow, DateHelper.LastDayOfWeekInMonth(y, m, dow) }).Dump();
"".Dump();
for(int i = 1; i <= 6; i++)
String.Format("{0} #{1}: {2}", new object[] { dow, i, DateHelper.XthDayOfWeekInMonth(y, m, dow, i) }).Dump();
}
public class DateHelper
{
public static DateTime FirstDayOfWeekInMonth(int year, int month, DayOfWeek day)
{
DateTime res = new DateTime(year, month, 1);
int offset = -(res.DayOfWeek - day);
if (offset < 0)
offset += 7;
res = res.AddDays(offset);
return res;
}
public static DateTime LastDayOfWeekInMonth(int year, int month, DayOfWeek day)
{
DateTime res = FirstDayOfWeekInMonth(year, month + 1, day);
res = res.AddDays(-7);
return res;
}
public static DateTime XthDayOfWeekInMonth(int year, int month, DayOfWeek day, int x)
{
DateTime res = DateTime.MinValue;
if (x > 0)
{
res = FirstDayOfWeekInMonth(year, month, day);
if (x > 1)
res = res.AddDays((x - 1) * 7);
res = res.Year == year && res.Month == month ? res : DateTime.MinValue;
}
return res;
}
}
Печать
First Friday: 07/02/2014 00:00:00
Last Friday: 28/02/2014 00:00:00
Friday #1: 07/02/2014 00:00:00
Friday #2: 14/02/2014 00:00:00
Friday #3: 21/02/2014 00:00:00
Friday #4: 28/02/2014 00:00:00
Friday #5: 01/01/0001 00:00:00
Friday #6: 01/01/0001 00:00:00
Ответ 7
Это версия, которая использует LINQ и стиль функционального программирования.
Он работает следующим образом.
Сначала возьмите все дни месяца. Затем выберите только один из правильных дней (пятница). Наконец, возьмите n-й (3-й) элемент и вернитесь.
// dt: The date to start from (usually DateTime.Now)
// n: The nth occurance (3rd)
// weekday: the day of the week to look for
public DateTime GetNthWeekdayOfMonth(DateTime dt, int n, DayOfWeek weekday)
{
var days = Enumerable.Range(1, DateTime.DaysInMonth(dt.Year, dt.Month)).Select(day => new DateTime(dt.Year, dt.Month, day));
var weekdays = from day in days
where day.DayOfWeek == weekday
orderby day.Day ascending
select day;
int index = n - 1;
if (index >= 0 && index < weekdays.Count())
return weekdays.ElementAt(index);
else
throw new InvalidOperationException("The specified day does not exist in this month!");
}
Ответ 8
Я передаю это DateTime для начала месяца, на который я смотрю.
private DateTime thirdSunday(DateTime timeFrom)
{
List<DateTime> days = new List<DateTime>();
DateTime testDate = timeFrom;
while (testDate < timeFrom.AddMonths(1))
{
if (testDate.DayOfWeek == DayOfWeek.Friday)
{
days.Add(testDate);
}
testDate = testDate.AddDays(1);
}
return days[2];
}
Ответ 9
Я не знаю, как это сделать. Но это не слишком сложно для кода:
DateTime now = DateTime.Now;
for (int i = 0; i < 7; ++i)
{
DateTime d = new DateTime(now.Year, now.Month, i+1);
if (d.DayOfWeek == DayOfWeek.Friday)
{
return d.AddDays(14);
}
}
Ответ 10
Мое рассуждение похоже на это
- 15-я - первая возможная "третья пятница" (1,8,15)
- поэтому мы ищем первую пятницу или после 15-го
- DayOfWeek - это перечисление, начинающееся с
0
для воскресенья. - Поэтому вам нужно добавить элемент
5-(int)baseDay.DayOfWeek
в 15-й - За исключением того, что вышеуказанное смещение может быть отрицательным, которое мы исправляем добавлением 7, а затем выполняем по модулю 7.
В коде:
public static DateTime GetThirdFriday(int year, int month)
{
DateTime baseDay = new DateTime(year, month, 15);
int thirdfriday = 15 + ((12 - (int)baseDay.DayOfWeek) % 7);
return new DateTime(year, month, thirdfriday);
}
Поскольку возможны только 7 возможных результатов, вы также можете сделать это:
private readonly static int[] thirdfridays =
new int[] { 20, 19, 18, 17, 16, 15, 21 };
public static int GetThirdFriday(int year, int month)
{
DateTime baseDay = new DateTime(year, month, 15);
return thirdfridays[(int)baseDay.DayOfWeek];
}
Ответ 11
public DateTime GetThirdThursday(DateTime now)
{
DateTime ThirdThursday;
now = DateTime.Now;
string wkday;
DateTime firstday = new DateTime(now.Year, now.Month, 1);
ThirdThursday = firstday.AddDays(15);
// ThirdThursday = now.AddDays((now.Day - 1) * -1).AddDays(14);
wkday = ThirdThursday.DayOfWeek.ToString();
while (wkday.CompareTo("Thursday") < 0)
{
ThirdThursday.AddDays(1);
}
return ThirdThursday;
}
Ответ 12
int numday = 0;
int dayofweek = 5; //friday
DateTime thirdfriday;
for (int i = 0; i < (date.AddMonths(1) - date).Days && numday <3; i++)
{
if ((int)date.AddDays(i).DayOfWeek == dayofweek)
{
numday++;
}
if (numday == 3)
{
thirdfriday = date.AddDays(i);
}
}
Ответ 13
Извините, что вскочил в последнее время... Может помочь кому-то еще.
Начните говорить: петли, yuck. Слишком много кода, yuck. Не общий Достаточно, да.
Здесь простая функция со свободной перегрузкой.
public DateTime DateOfWeekOfMonth(int year, int month, DayOfWeek dayOfWeek, byte weekNumber)
{
DateTime tempDate = new DateTime(year, month, 1);
tempDate = tempDate.AddDays(-(tempDate.DayOfWeek - dayOfWeek));
return
tempDate.Day > (byte)DayOfWeek.Saturday
? tempDate.AddDays(7 * weekNumber)
: tempDate.AddDays(7 * (weekNumber - 1));
}
public DateTime DateOfWeekOfMonth(DateTime sender, DayOfWeek dayOfWeek, byte weekNumber)
{
return DateOfWeekOfMonth(sender.Year, sender.Month, dayOfWeek, weekNumber);
}
Ваше использование:
DateTime thirdFridayOfMonth = DateOfWeekOfMonth(DateTime.Now, DayOfWeek.Friday, 3);
Ответ 14
Вот мой алгоритм:
- Найдите количество дней до предстоящей пятницы.
- Инициализировать счетчик и установить его в 1. Вычтите семь дней с даты, возвращенной из [1], а затем сравните месяц с даты, возвращенной с датой, возвращенной из (1).
- Если месяцы не равны, верните счетчик из [2].
- Если месяцы равны, запишите в [2] и добавьте 1 к счетчику, созданному в [2].
Счетчик даст вам пятнадцатую пятницу месяца на эту дату (или на предстоящую пятницу).
Ответ 15
После великолепных работ нет подтверждения для появления. Вы можете найти любой n-й день для данного месяца даты либо от начала, либо до последнего. Укажите минус значение вхождения, если вы ищете от последнего.
public static DateTime GetDayOfMonth(DateTime dateValue, DayOfWeek dayOfWeek, int occurance)
{
List<DateTime> dayOfWeekRanges = new List<DateTime>();
//move to the first of th month
DateTime startOfMonth = new DateTime(dateValue.Year, dateValue.Month, 1);
//move startOfMonth to the dayOfWeek requested
while (startOfMonth.DayOfWeek != dayOfWeek)
startOfMonth = startOfMonth.AddDays(1);
do
{
dayOfWeekRanges.Add(startOfMonth);
startOfMonth = startOfMonth.AddDays(7);
} while (startOfMonth.Month == dateValue.Month);
bool fromLast = occurance < 0;
if (fromLast)
occurance = occurance * -1;
if (fromLast)
return dayOfWeekRanges[dayOfWeekRanges.Count - occurance];
else
return dayOfWeekRanges[occurance - 1];
}
Ответ 16
Вот мои два цента... Оптимизированное решение без ненужных циклов или тестов:
public static DateTime ThirdFridayOfMonth(DateTime dateTime)
{
int day = dateTime.Day;
return dateTime.AddDays(21 - day - ((int)dateTime.DayOfWeek + 37 - day) % 7);
}