1

例如,无论是否有 DST,每周六的中欧时间 08:00(或夏季的 08:00 CEST)都会发生重复事件。如何提出DateTime代表此事件的 s 列表?

4

2 回答 2

0

你在找这个吗?

List<DateTime> Schedule = new List<DateTime>();

DateTime Base = new DateTime(2013, 11, 9, 8, 0, 0);

for (int i = 0; i < 365; i++)
    Schedule.Add(Base.AddDays(i));
于 2013-11-11T03:04:09.010 回答
0

这是一种获取DateTimeOffset准确代表您所要求的值的列表的方法。如果您愿意,您可以转换为DateTime其中一个result.DateTimeresult.UtcDateTime取决于您要查找的内容。这将返回从今天起的接下来的 N 天,在提供的时区中,考虑到 DST。

public static IEnumerable<DateTimeOffset> GetNextDaysInZone(int count, DayOfWeek dayOfWeek, TimeSpan localTimeOfDay, string timeZoneId)
{
    // get today in the time zone specified
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
    DateTime today = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tz).Date;

    // figure out how many days we are away from the target day of week
    int adjustment = dayOfWeek - today.DayOfWeek + (dayOfWeek < today.DayOfWeek ? 7 : 0);

    // calculate and return the results
    return Enumerable.Range(0, count)
        .Select(x =>
        {
            DateTime dt = today.AddDays(x * 7 + adjustment).Add(localTimeOfDay);
            TimeSpan offset = tz.GetUtcOffset(dt);
            return new DateTimeOffset(dt, offset);
        });
}

示例用法:

DayOfWeek dayOfWeek = DayOfWeek.Saturday;
TimeSpan localTimeOfDay = new TimeSpan(8, 0, 0);

// Note: Despite the name, this represents Central European Time, including both CET and CEST.
string tzid = "Central Europe Standard Time";

var results = GetNextDaysInZone(5, dayOfWeek, localTimeOfDay, tzid);

foreach (var result in results)
{
    Console.WriteLine("{0:yyyy-MM-dd HH:mm:ss zzz} ({1:yyyy-MM-dd HH:mm:ss} UTC)", result, result.UtcDateTime);
}

结果:

2013-11-16 08:00:00 +01:00 (2013-11-16 07:00:00 UTC)
2013-11-23 08:00:00 +01:00 (2013-11-23 07:00:00 UTC)
2013-11-30 08:00:00 +01:00 (2013-11-30 07:00:00 UTC)
2013-12-07 08:00:00 +01:00 (2013-12-07 07:00:00 UTC)
2013-12-14 08:00:00 +01:00 (2013-12-14 07:00:00 UTC)

为了更好地衡量,如果您想放弃内置的日期/时间 api 并使用更强大和可靠的东西,我建议您尝试Noda Time。以下是您如何使用 Noda Time 执行与上述相同的操作。

public static IEnumerable<ZonedDateTime> GetNextDaysInZone(int count, IsoDayOfWeek dayOfWeek, LocalTime localTimeOfDay, string timeZoneId)
{
    // get today in the time zone specified
    DateTimeZone tz = DateTimeZoneProviders.Tzdb[timeZoneId];
    Instant now = SystemClock.Instance.Now;
    LocalDate today = now.InZone(tz).Date;

    // figure out how many days we are away from the target day of week
    int adjustment = dayOfWeek - today.IsoDayOfWeek + (dayOfWeek < today.IsoDayOfWeek ? 7 : 0);

    // calculate and return the results
    return Enumerable.Range(0, count)
        .Select(x => (today.PlusDays(x * 7 + adjustment) + localTimeOfDay).InZoneLeniently(tz));
}

示例用法:

IsoDayOfWeek dayOfWeek = IsoDayOfWeek.Saturday;
LocalTime localTimeOfDay = new LocalTime(8, 0, 0);

// This is just one of the zones that follows CET/CEST
string tzid = "Europe/Berlin";

var results = GetNextDaysInZone(5, dayOfWeek, localTimeOfDay, tzid);

LocalDateTimePattern localPattern = LocalDateTimePattern.CreateWithInvariantCulture("yyyy-MM-dd HH:mm:ss");
OffsetPattern offsetPattern = OffsetPattern.CreateWithInvariantCulture("m");
foreach (var result in results)
{
    Console.WriteLine("{0} {1} ({2} UTC)",
        localPattern.Format(result.LocalDateTime),
        offsetPattern.Format(result.Offset),
        localPattern.Format(result.WithZone(DateTimeZone.Utc).LocalDateTime));
}

结果:

2013-11-16 08:00:00 +01:00 (2013-11-16 07:00:00 UTC)
2013-11-23 08:00:00 +01:00 (2013-11-23 07:00:00 UTC)
2013-11-30 08:00:00 +01:00 (2013-11-30 07:00:00 UTC)
2013-12-07 08:00:00 +01:00 (2013-12-07 07:00:00 UTC)
2013-12-14 08:00:00 +01:00 (2013-12-14 07:00:00 UTC)

这两种方法都采用对夏令时转换日不存在或存在两次的时间进行宽松转换的路径。如果您不希望它宽容,那么您还有更多工作要做。但我认为这超出了你所要求的范围。

于 2013-11-11T05:08:35.557 回答