月の毎月の「月曜日」を取得するにはどうすればよいですか?月ごとに月曜日を取得するにはどうすればよいですか?
例です。
入力:11.July.2017(2017年7月11日)
出力:(3,10,17,24,31)
2017年7月3日月曜日
2017年7月10日月曜日
2017年7月17日月曜日
2017年7月24日月曜日
2017年7月31日
私は与えられた月の日数を得ることができるが(2017年7月の場合は、31日です)。次に、dayOfWeekが月曜日に等しい場合は繰り返しを記述します(forループa.e.)。リストに追加します。しかし、forループは31回動作するので、これは良いコードではありません。目標をアーカイブするにはより良いアルゴリズムが必要です。
私はC#の.NET Frameworkを使用してい4.6
UPDATE
のためのすべてのための 感謝はあなたの助け、私がこれまで持っているいくつかの答えの後、私は単純な&の汚れたベンチマークコードですべてのコードをテストし、より高速なアルゴリズムを見つけました。
私のベンチマークコードです。
using System;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Columns;
using BenchmarkDotNet.Attributes.Jobs;
using BenchmarkDotNet.Engines;
using X.Core.Helpers;
namespace X.ConsoleBenchmark
{
[SimpleJob(RunStrategy.ColdStart, targetCount: 5)]
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
public class LoopTest
{
[Benchmark]
public void CalculateNextSalaryDateWithLoopAllDays()
{
DateTime date = new DateTime(2017, 7, 3);
const int oneMillion = 1000000;
for (int i = 0; i < oneMillion; i++)
{
List<DateTime> allXDaysInMonth = date.GetAllXDaysInMonthWithLoopAllDays(DayOfWeek.Tuesday);
if (allXDaysInMonth != null && allXDaysInMonth.FirstOrDefault().Day != 4)
{
throw new ApplicationException("Calculate method has errors.");
}
}
}
[Benchmark]
public void CalculateNextSalaryDate()
{
DateTime date = new DateTime(2017, 7, 3);
const int oneMillion = 1000000;
for (int i = 0; i < oneMillion; i++)
{
List<DateTime> allXDaysInMonth = date.GetAllXDaysInMonth(DayOfWeek.Tuesday);
if (allXDaysInMonth != null && allXDaysInMonth.FirstOrDefault().Day != 4)
{
throw new ApplicationException("Calculate method has errors.");
}
}
}
[Benchmark]
public void Maccettura_GetAllDayOfWeekPerMonth()
{
DateTime exampleDate = new DateTime(2017, 7, 3);
const int oneMillion = 1000000;
for (int i = 0; i < oneMillion; i++)
{
var date = new DateTime(exampleDate.Year, exampleDate.Month, 1);
if (date.DayOfWeek != DayOfWeek.Thursday)
{
int daysUntilDayOfWeek = ((int)DayOfWeek.Thursday - (int)date.DayOfWeek + 7) % 7;
date = date.AddDays(daysUntilDayOfWeek);
}
List<DateTime> days = new List<DateTime>();
while (date.Month == exampleDate.Month)
{
days.Add(date);
date = date.AddDays(7);
}
if (days.FirstOrDefault().Day != 6)
{
throw new ApplicationException("Calculate method has errors.");
}
}
}
[Benchmark]
public void ScottHannen_GetWeekdaysForMonth()
{
DateTime exampleDate = new DateTime(2017, 7, 3);
const int oneMillion = 1000000;
for (int i = 0; i < oneMillion; i++)
{
IEnumerable<DateTime> days = ScottHannen_GetDaysInMonth(exampleDate).Where(day => day.DayOfWeek == DayOfWeek.Thursday);
if (days.FirstOrDefault().Day != 6)
{
throw new ApplicationException("Calculate method has errors.");
}
}
}
private IEnumerable<DateTime> ScottHannen_GetDaysInMonth(DateTime date)
{
var dateLoop = new DateTime(date.Year, date.Month, 1);
while (dateLoop.Month == date.Month)
{
yield return dateLoop;
dateLoop = dateLoop.AddDays(1);
}
}
[Benchmark]
public void Trioj_GetWeekdaysForMonth()
{
DateTime exampleDate = new DateTime(2017, 7, 3);
const int oneMillion = 1000000;
for (int i = 0; i < oneMillion; i++)
{
IEnumerable<DateTime> days = Trioj_GetDatesInMonthByWeekday(exampleDate, DayOfWeek.Thursday);
if (days.FirstOrDefault().Day != 6)
{
throw new ApplicationException("Calculate method has errors.");
}
}
}
private List<DateTime> Trioj_GetDatesInMonthByWeekday(DateTime date, DayOfWeek dayOfWeek)
{
// We know the first of the month falls on, well, the first.
var first = new DateTime(date.Year, date.Month, 1);
int daysInMonth = DateTime.DaysInMonth(date.Year, date.Month);
// Find the first day of the week that matches the requested day of week.
if (first.DayOfWeek != dayOfWeek)
{
first = first.AddDays(((((int)dayOfWeek - (int)first.DayOfWeek) + 7) % 7));
}
// A weekday in a 31 day month will only occur five times if it is one of the first three weekdays.
// A weekday in a 30 day month will only occur five times if it is one of the first two weekdays.
// A weekday in February will only occur five times if it is the first weekday and it is a leap year.
// Incidentally, this means that if we subtract the day of the first occurrence of our weekday from the
// days in month, then if that results in an integer greater than 27, there will be 5 occurrences.
int maxOccurrences = (daysInMonth - first.Day) > 27 ? 5 : 4;
var list = new List<DateTime>(maxOccurrences);
for (int i = 0; i < maxOccurrences; i++)
{
list.Add(new DateTime(first.Year, first.Month, (first.Day + (7 * i))));
}
return list;
}
[Benchmark]
public void Jonathan_GetWeekdaysForMonth()
{
DateTime exampleDate = new DateTime(2017, 7, 3);
const int oneMillion = 1000000;
for (int i = 0; i < oneMillion; i++)
{
IEnumerable<DateTime> days = Jonathan_AllDatesInMonth(exampleDate.Year, exampleDate.Month).Where(x => x.DayOfWeek == DayOfWeek.Thursday);
if (days.FirstOrDefault().Day != 6)
{
throw new ApplicationException("Calculate method has errors.");
}
}
}
private static IEnumerable<DateTime> Jonathan_AllDatesInMonth(int year, int month)
{
int days = DateTime.DaysInMonth(year, month);
for (int day = 1; day <= days; day++)
{
yield return new DateTime(year, month, day);
}
}
[Benchmark]
public void Swatsonpicken_GetWeekdaysForMonth()
{
DateTime exampleDate = new DateTime(2017, 7, 3);
const int oneMillion = 1000000;
for (int i = 0; i < oneMillion; i++)
{
IEnumerable<DateTime> days = Swatsonpicken_GetDaysOfWeek(exampleDate, DayOfWeek.Thursday);
if (days.FirstOrDefault().Day != 6)
{
throw new ApplicationException("Calculate method has errors.");
}
}
}
private static IEnumerable<DateTime> Swatsonpicken_GetDaysOfWeek(DateTime startDate, DayOfWeek desiredDayOfWeek)
{
var daysOfWeek = new List<DateTime>();
var workingDate = new DateTime(startDate.Year, startDate.Month, 1);
var offset = ((int)desiredDayOfWeek - (int)workingDate.DayOfWeek + 7) % 7;
// Jump to the first desired day of week.
workingDate = workingDate.AddDays(offset);
do
{
daysOfWeek.Add(workingDate);
// Jump forward seven days to get the next desired day of week.
workingDate = workingDate.AddDays(7);
} while (workingDate.Month == startDate.Month);
return daysOfWeek;
}
[Benchmark]
public void AliaksandrHmyrak_GetWeekdaysForMonth()
{
DateTime exampleDate = new DateTime(2017, 7, 3);
const int oneMillion = 1000000;
for (int i = 0; i < oneMillion; i++)
{
IEnumerable<DateTime> days = AliaksandrHmyrak_GetDaysOfWeek(exampleDate, DayOfWeek.Thursday);
if (days.FirstOrDefault().Day != 6)
{
throw new ApplicationException("Calculate method has errors.");
}
}
}
private static List<DateTime> AliaksandrHmyrak_GetDaysOfWeek(DateTime date, DayOfWeek dayOfWeek)
{
var daysInMonth = DateTime.DaysInMonth(date.Year, date.Month);
var i = 1;
List<DateTime> result = new List<DateTime>(5);
do
{
var testDate = new DateTime(date.Year, date.Month, i);
if (testDate.DayOfWeek == dayOfWeek)
{
result.Add(testDate);
i += 7;
}
else
{
i++;
}
} while (i <= daysInMonth);
return result;
}
}
}
私はあなたが
をしたい場合、私はジョナサンの答えをマークし任意のコードと画像名を削除することができます。シンプルでクリーンで速く(興味深いことに)。ここで
月の最初の節目に移動します。あなたが目標月にいる限り、7日間を追加します。 – litelite
まあ、月曜日は7日ごとです。月の31日のすべてを通過する必要はありません。どの曜日が最初の月曜日であるかを決定することに基づいて、その月の最初の日であり、その後は毎週月曜日のループである。 –
@litelite(と@Sam)あなたの迅速な対応に感謝します。しかし、私は月に何mondaysを知りません。例は2017年8月に4つの月曜日がありますが、2017年には5があります。私は最後の日付が実際には32.07.2017のように存在することを確認できました。あるいは、与えられた日付の月曜日にどれくらいの日数を数えれば、+7を加えることができます。しかし、私はより良いアプローチを探しています。 –