【问题标题】:How to handle vague dates in .Net如何在.Net中处理模糊的日期
【发布时间】:2011-07-27 16:04:27
【问题描述】:

我有一个系统,它从外部来源获取信息,然后将其存储以供以后显示。

其中一个数据项是日期。在源系统上,他们有模糊日期的概念,即不准确到特定的日期,有时也不准确到一个月。所以我得到格式的日期:

dd/mm/yyyy
mm/yyyy
yyyy

我可以将这些解析为 DateTime 对象并使用它们,但是在稍后渲染时,我需要能够确定日期的准确性,因为解析“2010”将导致日期为“01/01/2010”。我只想显示年份,所以需要知道它的原始准确性。

我已经模拟了一个快速课程来处理这个问题:

public class FuzzyDate
{
    public DateTime Date { get; set; }
    public DateType Type { get; set; }
}

public enum DateType
{
    DayMonthYear,
    MonthYear,
    Year
}

这将为我完成这项工作,我可以在解析时做一些事情来处理它,但我觉得这可能是一个很常见的问题,并且可能有一个现有的更清洁的解决方案。

.Net 中是否有内置功能可以做到这一点?我看过文化资料,但似乎不太对。

任何帮助将不胜感激。

【问题讨论】:

  • 我不知道有什么内置的东西可以支持这一点。我建议看一下 NodaTime (code.google.com/p/noda-time) - 虽然我在浏览该源代码时看不到任何可以专门解决您的问题的东西,但您可能会。还要考虑存储字符串格式表示(或对格式的引用)而不是枚举值的可能性 - 这允许您在需求发生变化时添加新的日期存储格式而无需重新编译和重新部署。

标签: c# .net datetime


【解决方案1】:

回答您的问题:.NET 中没有内置任何东西可以优雅地处理这个问题。

您的解决方案与我见过的任何解决方案一样有效。您可能希望通过重写 ToString() 方法来修饰您的类,该方法将根据 DateType 适当地呈现您的日期。

这里有几个其他线程试图解决这个问题:

祝你好运!

【讨论】:

    【解决方案2】:

    如果您的数据类型将始终处理特定时间段(即 1972 年是特定时间段,但 7 月 4 日不是特定时间段),您可以将数据存储为开始时间和时间跨度。

    • 如果您的日期为“1972”,则开始日期为 19720101,时间跨度为 366 天。
    • 如果您的日期为“07/1972”,则开始日期为 19720701,时间跨度为 31 天。
    • 如果您的日期为“04/07/1972”,则开始日期为 19720704,时间跨度为 1 天。

    这是一个可能的实现:

    public struct VagueDate
    {
        DateTime start, end;
    
        public DateTime Start { get { return start; } }
        public DateTime End { get { return end; } }
        public TimeSpan Span { get { return end - start; } }
    
        public VagueDate(string Date)
        {
            if (DateTime.TryParseExact(Date, "yyyy", null, 0, out start))
                end = start.AddYears(1);
            else if (DateTime.TryParseExact(Date, "MM/yyyy", null, 0, out start))
                end = start.AddMonths(1);
            else if (DateTime.TryParseExact(Date, "dd/MM/yyyy", null, 0, out start))
                end = start.AddDays(1);
            else
                throw new ArgumentException("Invalid format", "Date");
        }
    
        public override string ToString()
        {
            return Start.ToString("dd/MM/yyyy") + " plus " + Span.TotalDays + " days";
        }
    }
    

    【讨论】:

      【解决方案3】:

      当我开始阅读您的问题时,我很快得出结论,答案是实现您自己的 FuzzyDate 类。瞧,这正是你所做的。

      我可以想象,随着时间的推移,您可能希望为此添加功能(例如考虑到 DateType 的比较)。

      我认为在 .NET Framework 中没有任何东西可以固有地帮助您,所以我认为您在做正确的事情。

      【讨论】:

        【解决方案4】:

        我认为你走对了路。没有“模糊”日期或部分日期的概念,您需要自己构建。

        你可能需要更多的构造方法,例如

        public FuzzyDate(int year)
        {
           Date = new DateTime(year,1,1); // 1 Jan yy
           Type = DateType.Year;
        }
        
        public FuzzyDate(int year, int month)
        {
           Date = new DateTime(year, month, 1); // 1 mm yy
           Type = DateType.MonthYear;
        }
        
        public FuzzyDate(int year, int month, int day)
        {
           Date = new DateTime(year, month, day); // dd mm yy
           Type = DateType.DayMonthYear;
        }
        

        希望这会有所帮助, 凯文

        【讨论】:

          【解决方案5】:

          在我看来,您的方法是正确的。 .NET DateTime 确实支持多种格式,但我想鉴于所有这些格式都支持步骤(纳秒)的概念,那么将与特定的日期和时间相关。

          【讨论】:

            【解决方案6】:

            我会做不同的事情是使用可空值(或使用 -1 表示空语义)来表示月份和日期,以指示收集了哪些数据。然后我会有一个工厂方法,它接受一个 DateType 参数并返回一个 DateTime。如果只有年份可用并且客户端代码尝试创建 DateType.DayMonthYear,则此方法将抛出异常。

            public class FuzzyDate
            {
                int _year;
                int? _month;
                int? _day;
            
                public DateTime Date { get; set; }
                public DateType Type { get; set; }
            
                public DateTime GetDateTime(DateType dateType) { // ...
            }
            
            public enum DateType
            {
                DayMonthYear,
                MonthYear,
                Year
            }
            

            这可能看起来有点过头了,但该方法会显式存储原始数据,并且仅在请求时表示“伪造”的 DateTime 对象。如果您要在内部保留一个 DateTime 对象以及一个 DateType 枚举,您将失去一些分辨率。

            【讨论】:

            • 我很难想象有一年零一天但没有一个月。我更喜欢 OP 的 DateTypes 枚举方法
            • 就此而言,我更容易想象想要存储没有年份的月份和日期:例如,在不知道年龄的情况下存储一个人的生日。在这种情况下,“日” 日,没有它就没有任何意义。
            • @Neil:OP 的方法很好。我担心的是在捕获时明确存储数据的状态,一旦将标志附加到被黑的 DateTime 值,就会丢失。
            • @djacobson:模糊日期问题实际上在很多领域都很常见。例如,发展中国家的人们往往只知道他们出生的年份,而不知道月份或日期。有时他们甚至不知道这一点,因此必须记录一个近似值。在这种情况下,最好使用带有布尔标志(例如 Approximate 和 GovernmentIdValidated)的模糊日期对象存储额外信息...
            【解决方案7】:

            据我所知,.NET 中没有为此内置任何内容,我要采用的解决方案是基于可空值的解决方案,类似于这样。

            public class FuzzyDate
            {
                private int Year;
                private int? Month;
                private int? Day;
            
                public FuzzyDate(int Year, int? Month, int? Day)
                {
                    this.Year = Year;
                    this.Month = Month;
                    this.Day = Day;
                }
            
                public DateType DateType
                {
                    get
                    {
                        if(Day.HasValue && Month.HasValue)
                        {
                            return DateType.DayMonthYear;
                        }
                        else if(Month.HasValue)
                        {
                            return DateType.MonthYear;
                        }
                        else
                        {
                            return DateType.Year;
                        }
                    }
                }
            
                public DateTime Date
                {
                    get
                    {
                        return new DateTime(Year, Month.GetValueOrDefault(1), Day.GetValueOrDefault(1));
                    }
                }
            }
            
            public enum DateType
            {
                DayMonthYear,
                MonthYear,
                Year
            }
            

            【讨论】:

              【解决方案8】:

              您可以根据日期时间创建自己的结构(用户定义的类型),允许 00 表示月份,00 表示一天...然后还实现 icomparable,因此您可以对其进行数学/比较。

              http://msdn.microsoft.com/en-us/library/k69kzbs1%28v=vs.71%29.aspx
              http://msdn.microsoft.com/en-us/library/system.icomparable.aspx

              【讨论】:

                猜你喜欢
                • 2017-03-10
                • 1970-01-01
                • 2015-06-03
                • 2013-11-22
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多