顺序 - 随后几年的同一日期
Sequence - the same date in following years
我想创建一个序列,结果是 returns 所有年份的星期几与函数参数中的相同
(例如:自开始日期起,2 月 12 日为星期日的所有年份)。
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
seq {
...
}
希望你明白我的意思。
这个怎么样:
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
Seq.initInfinite ((+)1) // from 1..∞
|> Seq.map start.AddYears
|> Seq.takeWhile (fun x -> x < DateTime.MaxValue)
|> Seq.filter (fun x -> x.DayOfWeek = dw)
|> Seq.map (fun x -> x.Year)
myDate System.DayOfWeek.Monday (new DateTime(2001,1,1)) |> Dump
或
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
let rec inner i =
seq {
let someDay = start.AddYears(i)
if someDay.DayOfWeek = dw then yield someDay.Year
yield! inner (i+1)
}
inner 1
myDate System.DayOfWeek.Monday (new DateTime(2001,12,1)) |> Dump
Stuart 的回答很好,但我忍不住想 "eh, I'd delete some of that code." 你知道的,从那个特定 month/day 的未终止年份序列开始,让来电者决定要拿多少或添加自己的过滤器。
此时你应该在思考 "fool's errand"。 :) 我 运行 遇到的第一个问题——因为我的第二个微弱测试失败了——是你不能愉快地继续递增 DateTime
永远,所以你必须编写代码来限制它。
因此,由于要处理变幻莫测的真实数据,我最终得到的代码更多而不是更少:
// All instances of this specified month/day beginning with 'start'.
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
// Start with a sequence of one date for each year...
seq {
// Don't run the date past DateTime.MaxValue, there lurks an
// ArgumentOutOfRangeException. Comparison also must be on the
// valid side of DateTime.MaxValue. Don't bother with try/with
// here in a sequence expression, you can't do that.
let maxDateBarrier = DateTime.MaxValue.AddYears(-1)
let mutable keepGoing, date = true, start
while keepGoing do
yield date
// if date.Year % 100 = 0 then printfn "%A" date.Year
if date <= maxDateBarrier then
date <- date.AddYears(1)
else
keepGoing <- false
}
|> Seq.where (fun date -> date.DayOfWeek = dw)
有点啰嗦。测试 #1 工作正常:
let printDates (dates : DateTime seq) =
for date in dates do
printfn "%A" date.Year
// Take the next 5
myDate DayOfWeek.Sunday DateTime.Now
|> Seq.take 5
|> printDates
测试 #2 实际上遍历了我序列中的 所有 个日期:
// Take up to 5 before 2040.
// Note: this statement actually iterates through *all* the years in the
// sequence if you truncate to a length longer than Seq.where returns.
myDate DayOfWeek.Sunday (DateTime(2017, 2, 13))
|> Seq.where (fun date -> date.Year < 2040)
|> Seq.truncate 5
|> printDates
测试 #2 是向 myDate
函数添加 endDate
的原因吗?不,更多的是更好地使用序列的争论。使用 takeWhile
而不是 where
:
// Try again: Take up to 5 before 2040.
// Terminate the sequence early with takeWhile.
myDate DayOfWeek.Sunday (DateTime(2017, 2, 13))
|> Seq.takeWhile (fun date -> date.Year < 2040)
|> Seq.truncate 5
|> printDates
好多了。错过了 "less code," 的目标,但我可以接受。 :)
我懒得编写代码,但我会通过这种方式找到一种有效且快速的算法,并将闰年考虑在内。我认为这是一个有趣的任务,将速度与其他答案进行比较会很有趣。
有 14 种可能的日历。如果您 google 它,您可以很快找到这些日历如何重复。我找到了这个。
"The Gregorian calendar repeats itself in 28-year cycles. A calendar for a particular non-leap year repeats itself after 11 years twice and repeats itself after six years once in a 28-year span. Calendars for leap years repeat themselves every 28 years."
一年中特定的一天是如何重复的,我想可能会稍微复杂一些,但如果是这样的话就不会复杂很多。
七个 non-leap 日历中的任何一个当然会与从 1 月到 2 月的闰年日历中的一个相匹配,当然除了 2 月 29 日。乍一看似乎很明显,从 3 月开始也将有一场比赛,只是与 1 月 28 日相比,它将有一天和一个日历的偏差。需要检查。我想知道这是否会影响算法,如果会,如何影响。
如果您输入的是 2 月 29 日,那么显然只需要考虑闰年。
由此看来,写一个算法应该很简单了。
希望这是有道理的。我不确定每 400 年会发生什么,或者是否会出现其他问题。但是 运行 通过所有合理的日期来测试并根据需要进行调整是很容易的。
我想创建一个序列,结果是 returns 所有年份的星期几与函数参数中的相同 (例如:自开始日期起,2 月 12 日为星期日的所有年份)。
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
seq {
...
}
希望你明白我的意思。
这个怎么样:
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
Seq.initInfinite ((+)1) // from 1..∞
|> Seq.map start.AddYears
|> Seq.takeWhile (fun x -> x < DateTime.MaxValue)
|> Seq.filter (fun x -> x.DayOfWeek = dw)
|> Seq.map (fun x -> x.Year)
myDate System.DayOfWeek.Monday (new DateTime(2001,1,1)) |> Dump
或
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
let rec inner i =
seq {
let someDay = start.AddYears(i)
if someDay.DayOfWeek = dw then yield someDay.Year
yield! inner (i+1)
}
inner 1
myDate System.DayOfWeek.Monday (new DateTime(2001,12,1)) |> Dump
Stuart 的回答很好,但我忍不住想 "eh, I'd delete some of that code." 你知道的,从那个特定 month/day 的未终止年份序列开始,让来电者决定要拿多少或添加自己的过滤器。
此时你应该在思考 "fool's errand"。 :) 我 运行 遇到的第一个问题——因为我的第二个微弱测试失败了——是你不能愉快地继续递增 DateTime
永远,所以你必须编写代码来限制它。
因此,由于要处理变幻莫测的真实数据,我最终得到的代码更多而不是更少:
// All instances of this specified month/day beginning with 'start'.
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
// Start with a sequence of one date for each year...
seq {
// Don't run the date past DateTime.MaxValue, there lurks an
// ArgumentOutOfRangeException. Comparison also must be on the
// valid side of DateTime.MaxValue. Don't bother with try/with
// here in a sequence expression, you can't do that.
let maxDateBarrier = DateTime.MaxValue.AddYears(-1)
let mutable keepGoing, date = true, start
while keepGoing do
yield date
// if date.Year % 100 = 0 then printfn "%A" date.Year
if date <= maxDateBarrier then
date <- date.AddYears(1)
else
keepGoing <- false
}
|> Seq.where (fun date -> date.DayOfWeek = dw)
有点啰嗦。测试 #1 工作正常:
let printDates (dates : DateTime seq) =
for date in dates do
printfn "%A" date.Year
// Take the next 5
myDate DayOfWeek.Sunday DateTime.Now
|> Seq.take 5
|> printDates
测试 #2 实际上遍历了我序列中的 所有 个日期:
// Take up to 5 before 2040.
// Note: this statement actually iterates through *all* the years in the
// sequence if you truncate to a length longer than Seq.where returns.
myDate DayOfWeek.Sunday (DateTime(2017, 2, 13))
|> Seq.where (fun date -> date.Year < 2040)
|> Seq.truncate 5
|> printDates
测试 #2 是向 myDate
函数添加 endDate
的原因吗?不,更多的是更好地使用序列的争论。使用 takeWhile
而不是 where
:
// Try again: Take up to 5 before 2040.
// Terminate the sequence early with takeWhile.
myDate DayOfWeek.Sunday (DateTime(2017, 2, 13))
|> Seq.takeWhile (fun date -> date.Year < 2040)
|> Seq.truncate 5
|> printDates
好多了。错过了 "less code," 的目标,但我可以接受。 :)
我懒得编写代码,但我会通过这种方式找到一种有效且快速的算法,并将闰年考虑在内。我认为这是一个有趣的任务,将速度与其他答案进行比较会很有趣。
有 14 种可能的日历。如果您 google 它,您可以很快找到这些日历如何重复。我找到了这个。
"The Gregorian calendar repeats itself in 28-year cycles. A calendar for a particular non-leap year repeats itself after 11 years twice and repeats itself after six years once in a 28-year span. Calendars for leap years repeat themselves every 28 years."
一年中特定的一天是如何重复的,我想可能会稍微复杂一些,但如果是这样的话就不会复杂很多。
七个 non-leap 日历中的任何一个当然会与从 1 月到 2 月的闰年日历中的一个相匹配,当然除了 2 月 29 日。乍一看似乎很明显,从 3 月开始也将有一场比赛,只是与 1 月 28 日相比,它将有一天和一个日历的偏差。需要检查。我想知道这是否会影响算法,如果会,如何影响。
如果您输入的是 2 月 29 日,那么显然只需要考虑闰年。
由此看来,写一个算法应该很简单了。
希望这是有道理的。我不确定每 400 年会发生什么,或者是否会出现其他问题。但是 运行 通过所有合理的日期来测试并根据需要进行调整是很容易的。