ループ/カウンタ型の恐ろしいソリューションを使用せずにこれを行う方法もわかりません。問題は次のとおりです。
開始日と終了日という2つの日付が指定されており、指定された間隔で何らかのアクションを実行する必要があります。たとえば、2009年3月26日までの3日ごとの2009年3月10日から2009年3月26日までのすべての日付について、リストにエントリを作成する必要があります。したがって、私の入力は次のようになります。
DateTime StartDate = "3/10/2009";
DateTime EndDate = "3/26/2009";
int DayInterval = 3;
私の出力は、次の日付を持つリストになります。
3/13/2009 3/16/2009 3/19/2009 3/22/2009 3/25/2009
では、このようなことをどのように行うのでしょうか? forループを使用して、範囲内の毎日を次のように個別のカウンターで繰り返すことを考えました。
int count = 0;
for(int i = 0; i < n; i++)
{
count++;
if(count >= DayInterval)
{
//take action
count = 0;
}
}
しかし、もっと良い方法があるように思えますか?
まあ、あなたはそれらを何らかの方法でループする必要があります。私はこのようなメソッドを定義することを好みます:
public IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for(var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
yield return day;
}
その後、次のように使用できます。
foreach (DateTime day in EachDay(StartDate, EndDate))
// print it or whatever
この方法で、1日おき、3日おき、平日のみなどをヒットできます。たとえば、「開始」日から3日ごとに戻るには、AddDays(3)
の代わりにループでAddDays(1)
を呼び出すだけです。
MiscUtil にRange
クラスがあり、便利だと思います。さまざまな拡張メソッドと組み合わせて、次のことができます。
foreach (DateTime date in StartDate.To(EndDate).ExcludeEnd()
.Step(DayInterval.Days())
{
// Do something with the date
}
(終了を除外する場合もしない場合もあります。例として提供したいと思っただけです。)
これは基本的に、既製の(およびより汎用的な)mquanderのソリューションの形式です。
あなたの例では、試すことができます
DateTime StartDate = new DateTime(2009, 3, 10);
DateTime EndDate = new DateTime(2009, 3, 26);
int DayInterval = 3;
List<DateTime> dateList = new List<DateTime>();
while (StartDate.AddDays(DayInterval) <= EndDate)
{
StartDate = StartDate.AddDays(DayInterval);
dateList.Add(StartDate);
}
拡張機能で使用される@mquanderおよび@Yogurt The Wiseのコード:
public static IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for (var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
yield return day;
}
public static IEnumerable<DateTime> EachMonth(DateTime from, DateTime thru)
{
for (var month = from.Date; month.Date <= thru.Date || month.Month == thru.Month; month = month.AddMonths(1))
yield return month;
}
public static IEnumerable<DateTime> EachDayTo(this DateTime dateFrom, DateTime dateTo)
{
return EachDay(dateFrom, dateTo);
}
public static IEnumerable<DateTime> EachMonthTo(this DateTime dateFrom, DateTime dateTo)
{
return EachMonth(dateFrom, dateTo);
}
1年後、それは誰かを助けますように、
このバージョンには、より柔軟にするために述語が含まれています。
var today = DateTime.UtcNow;
var birthday = new DateTime(2018, 01, 01);
var toBirthday = today.RangeTo(birthday);
var toBirthday = today.RangeTo(birthday, x => x.AddMonths(2));
var toBirthday = today.RangeTo(birthday, x => x.AddYears(1));
RangeFrom
を使用してください// same result
var fromToday = birthday.RangeFrom(today);
var toBirthday = today.RangeTo(birthday);
public static class DateTimeExtensions
{
public static IEnumerable<DateTime> RangeTo(this DateTime from, DateTime to, Func<DateTime, DateTime> step = null)
{
if (step == null)
{
step = x => x.AddDays(1);
}
while (from < to)
{
yield return from;
from = step(from);
}
}
public static IEnumerable<DateTime> RangeFrom(this DateTime to, DateTime from, Func<DateTime, DateTime> step = null)
{
return from.RangeTo(to, step);
}
}
fromDate > toDate
の場合は例外をスローできますが、[]
の代わりに空の範囲を返すことを好みます
DateTime startDate = new DateTime(2009, 3, 10);
DateTime stopDate = new DateTime(2009, 3, 26);
int interval = 3;
for (DateTime dateTime=startDate;
dateTime < stopDate;
dateTime += TimeSpan.FromDays(interval))
{
}
DateTime startDate = new DateTime(2009, 3, 10);
DateTime stopDate = new DateTime(2009, 3, 26);
int interval = 3;
while ((startDate = startDate.AddDays(interval)) <= stopDate)
{
// do your thing
}
問題に応じて、これを試すことができます...
// looping between date range
while (startDate <= endDate)
{
//here will be your code block...
startDate = startDate.AddDays(1);
}
ありがとう......
代わりにイテレータを記述することを検討してください。これにより、「++」のような通常の「for」ループ構文を使用できます。検索して、同様の質問を見つけました answered ここでStackOverflowでDateTimeを反復可能にするための指針を与えます。
DateTime.AddDays()
関数を使用してDayInterval
をStartDate
に追加し、EndDate
より小さいことを確認できます。
DateTime begindate = Convert.ToDateTime("01/Jan/2018");
DateTime enddate = Convert.ToDateTime("12 Feb 2018");
while (begindate < enddate)
{
begindate= begindate.AddDays(1);
Console.WriteLine(begindate + " " + enddate);
}
ここでは、ループ内でより良い解決策となる日付を逃さないように注意する必要があります。
これにより、startdateの最初の日付が得られ、それをインクリメントする前にループで使用すると、enddateの最終日を含むすべての日付が処理されるため、<= enddateとなります。
したがって、上記の答えは正しいものです。
while (startdate <= enddate)
{
// do something with the startdate
startdate = startdate.adddays(interval);
}
これを使用できます。
DateTime dt0 = new DateTime(2009, 3, 10);
DateTime dt1 = new DateTime(2009, 3, 26);
for (; dt0.Date <= dt1.Date; dt0=dt0.AddDays(3))
{
//Console.WriteLine(dt0.Date.ToString("yyyy-MM-dd"));
//take action
}
@ jacob-sobusと@mquanderと@Yogurtは正確に正しくありません。次の日が必要な場合、ほとんど00:00の時間を待ちます
public static IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for (var day = from.Date; day.Date <= thru.Date; day = day.NextDay())
yield return day;
}
public static IEnumerable<DateTime> EachMonth(DateTime from, DateTime thru)
{
for (var month = from.Date; month.Date <= thru.Date || month.Year == thru.Year && month.Month == thru.Month; month = month.NextMonth())
yield return month;
}
public static IEnumerable<DateTime> EachYear(DateTime from, DateTime thru)
{
for (var year = from.Date; year.Date <= thru.Date || year.Year == thru.Year; year = year.NextYear())
yield return year;
}
public static DateTime NextDay(this DateTime date)
{
return date.AddTicks(TimeSpan.TicksPerDay - date.TimeOfDay.Ticks);
}
public static DateTime NextMonth(this DateTime date)
{
return date.AddTicks(TimeSpan.TicksPerDay * DateTime.DaysInMonth(date.Year, date.Month) - (date.TimeOfDay.Ticks + TimeSpan.TicksPerDay * (date.Day - 1)));
}
public static DateTime NextYear(this DateTime date)
{
var yearTicks = (new DateTime(date.Year + 1, 1, 1) - new DateTime(date.Year, 1, 1)).Ticks;
var ticks = (date - new DateTime(date.Year, 1, 1)).Ticks;
return date.AddTicks(yearTicks - ticks);
}
public static IEnumerable<DateTime> EachDayTo(this DateTime dateFrom, DateTime dateTo)
{
return EachDay(dateFrom, dateTo);
}
public static IEnumerable<DateTime> EachMonthTo(this DateTime dateFrom, DateTime dateTo)
{
return EachMonth(dateFrom, dateTo);
}
public static IEnumerable<DateTime> EachYearTo(this DateTime dateFrom, DateTime dateTo)
{
return EachYear(dateFrom, dateTo);
}
15分ごとに繰り返す
DateTime startDate = DateTime.Parse("2018-06-24 06:00");
DateTime endDate = DateTime.Parse("2018-06-24 11:45");
while (startDate.AddMinutes(15) <= endDate)
{
Console.WriteLine(startDate.ToString("yyyy-MM-dd HH:mm"));
startDate = startDate.AddMinutes(15);
}