求购:DateTime.TryNew(年,月,日)或DateTime.IsValidDate(年,月,日) [英] Wanted: DateTime.TryNew(year, month, day) or DateTime.IsValidDate(year, month, day)

查看:163
本文介绍了求购:DateTime.TryNew(年,月,日)或DateTime.IsValidDate(年,月,日)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标题基本上说明了一切。我得到三个用户提供的整数( 1 从旧的数据库(我不能改变)。目前,我用下面的code解析这些整数到的DateTime 结构:

The title basically says it all. I'm getting three user-supplied integers (year, month, day)1 from a legacy database (which I cannot change). Currently, I use the following code to parse those integers into a DateTime structure:

try {
    return new DateTime(year, month, day);
} catch (ArgumentException ex) {
    return DateTime.MinValue;
}

有时候,值不重新present有效日期(是的,用户输入的东西,如1999年6月31日,不,继承应用程序没有验证这一点)。由于抛出异常时,数据验证失败被认为是不好练习,我倒是preFER与异常少code代替。不过,唯一的解决办法我能找到的是把整数转换成一个字符串和 TryParseExact 这个字符串,这似乎甚至丑陋的我。我错过了一些明显的更好的解决方案?

Sometimes, the values don't represent a valid date (yes, users enter stuff like 1999-06-31, and no, the legacy app did not verify this). Since throwing an exception when data validation fails is considered bad practice, I'd prefer to replace this with exception-less code. However, the only solution I could find was to convert the integers into one string and TryParseExact this string, which seems even uglier to me. Did I miss some obvious better solution?

1 事实上,它在格式YYYYMMDD有一个整数,但转换,为年,月,日是微不足道......

1 Actually, it's one integer in the format YYYYMMDD, but converting that to year, month and day is trivial...

推荐答案

没有一个静态函数 IsValidDate(),所以你必须自己写的,先天真实现可能是:

There is not a static function IsValidDate() so you have to write it by yourself, first naive implementation may be:

public static bool IsValidDate(int year, int month, int day)
{
    if (year < DateTime.MinValue.Year || year > DateTime.MaxValue.Year)
        return false;

    if (month < 1 || month > 12)
        return false;

    return day > 0 && day <= DateTime.DaysInMonth(year, month);
}

我说这是一个天真的实现,因为(除了参数范围)只检查,以查看是否有最新的存在的是闰年。在实践中,如果你正在使用非公历日历(和失踪已被用于调整日期从儒略历,即使在公历日),这可能失败,因为日程的问题。

I said this is a naive implementation because (besides arguments range) the only check to see if a date exists is for leap year. In practice this may fail because of calendar issues if you're working with non Gregorian calendars (and missing days even in Gregorian calendar that has been used to align date from Julian calendar).

这些假设可能被用于非公历日历破:

These assumptions may be broken for non Gregorian calendars:

  • 1 01月01日是最小的有效日期。这不是真的。不同的日历有不同的最小日期。这个限制仅仅是的DateTime 的技术限制,但有可能是日历(或日历内的时代)有不同的最小(和最大)的日期。
  • 个月,一年的数量比12小于或等于事实并非如此,在一些日历上限是13和它的并不总是相同的,每年的。
  • 如果日期是有效的(根据所有其他规则),那么它的有效日期。这不是真的,日历可能有不止一个时代,不是所有的日期是否有效(甚至可能是在时代的日期范围)。
  • 1 January 01 is smallest valid date. It's not true. Different calendars have a different smallest date. This limit is just DateTime technical limit but there may be a calendar (or an Era within a calendar) with a different minimum (and maximum) date.
  • Number of months in one year is less or equal than 12. It's not true, in some calendars upper bound is 13 and it's not always the same for every year.
  • If a date is valid (according all other rules) then it's a valid date. It's not true, a calendar may have more than one era and not all dates are valid (possibly even within era date range).

规则来管理这是pretty的复杂,它太容易忘记东西,所以,在这种情况下,捕获异常可能不是这样的坏主意。的previous验证功能的更好的版本可能只是提供基本的验证,并依靠的DateTime 来检查其他规则:

Rules to manage this are pretty complex and it's too easy to forget something so, in this case, catching an exception may not be such bad idea. A better version of previous validation function may just provide basic validation and relying on DateTime to check other rules:

public static DateTime? TryNew(int year,
                               int month,
                               int day,
                               Calendar calendar)
{
    if (calendar == null)
        calendar = new GregorianCalendar();

    if (year < calendar.MinSupportedDateTime.Year)
        return null;

    if (year > calendar.MaxSupportedDateTime.Year)
        return null;

    // Note that even with this check we can't assert this is a valid
    // month because one year may be "shared" for two eras moreover here
    // we're assuming current era.
    if (month < 1 || month > calendar.GetMonthsInYear(year))
        return null;

    if (day <= 0 || day > DateTime.DaysInMonth(year, month))
        return null;

    // Now, probably, date is valid but there may still be issues
    // about era and missing days because of calendar changes.
    // For all this checks we rely on DateTime implementation.        
    try
    {
        return new DateTime(year, month, day, calendar);
    }
    catch (ArgumentOutOfRangeException)
    {
        return null;
    }
}

然后,给这个新的功能,你原来的code应该是:

Then, given this new function, your original code should be:

return TryNew(year, month, day) ?? DateTime.MinValue;

这篇关于求购:DateTime.TryNew(年,月,日)或DateTime.IsValidDate(年,月,日)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆