strtotime equivalent in .NET

后端 未结 6 1178
春和景丽
春和景丽 2020-12-06 08:04

Is there an equivalent of PHP\'s strtotime() function working on .NET Framework. I\'m talking about it\'s capacity to handle strings likes:

  • strtot
相关标签:
6条回答
  • 2020-12-06 08:30

    I think you'll have to write your own method.

    "now" is just DateTime.Now.

    "+1 day" would be DateTime.Now.AddDays(1) for example.

    So you'll need to parse your string looking for this type of input and then call the appropriate DateTime method. The fall-through case would be to pass the string through DateTime.Parse(String, IFormatProvider, DateTimeStyles) with different DateTimeStyles.

    0 讨论(0)
  • 2020-12-06 08:33

    I think the 'correct' answer here is to use something like https://github.com/robertwilczynski/nChronic. It's a port of the Ruby equivalent and can parse a wide range of date time formats, as listed here: http://chronic.rubyforge.org/ in the 'Examples' section (scroll down).

    0 讨论(0)
  • 2020-12-06 08:36

    I think the best way this to write extension methods to DateTime to handle your needs.

    Maybe, it can be OSS, so the community can help you to implement it.

    0 讨论(0)
  • The DateTime struct has several methods and properties to get what you need:

    DateTime.Now;
    DateTime.Parse("10 September 2000");
    DateTime.Now.AddDays(1);
    DateTime.Now.AddDays(7);
    DateTime.Now.AddDays(9).AddHours(4).AddSeconds(2);
    // And so on
    

    If the functionality provided by the DateTime struct isn't enough, I'd suggest checking out the noda-time project (by Jon Skeet).

    0 讨论(0)
  • 2020-12-06 08:50
    DateTime date = new DateTime(10,10,2010)
    Response.Write(date.ToShortDateTimeString());
    Response.Write(date.Year);
    date = DateTime.Now;
    

    etc etc

    0 讨论(0)
  • 2020-12-06 08:57

    As so far there is no answer, I made it based on the example given. It supports most cases except those like "last Thurday" (or other days of the week).

    /// <summary>
    /// Parse a date/time string.
    /// 
    /// Can handle relative English-written date times like:
    ///  - "-1 day": Yesterday
    ///  - "+12 weeks": Today twelve weeks later
    ///  - "1 seconds": One second later from now.
    ///  - "5 days 1 hour ago"
    ///  - "1 year 2 months 3 weeks 4 days 5 hours 6 minutes 7 seconds"
    ///  - "today": This day at midnight.
    ///  - "now": Right now (date and time).
    ///  - "next week"
    ///  - "last month"
    ///  - "2010-12-31"
    ///  - "01/01/2010 1:59 PM"
    ///  - "23:59:58": Today at the given time.
    /// 
    /// If the relative time includes hours, minutes or seconds, it's relative to now,
    /// else it's relative to today.
    /// </summary>
    internal class RelativeDateParser
    {
        private const string ValidUnits = "year|month|week|day|hour|minute|second";
    
        /// <summary>
        /// Ex: "last year"
        /// </summary>
        private readonly Regex _basicRelativeRegex = new Regex(@"^(last|next) +(" + ValidUnits + ")$");
    
        /// <summary>
        /// Ex: "+1 week"
        /// Ex: " 1week"
        /// </summary>
        private readonly Regex _simpleRelativeRegex = new Regex(@"^([+-]?\d+) *(" + ValidUnits + ")s?$");
    
        /// <summary>
        /// Ex: "2 minutes"
        /// Ex: "3 months 5 days 1 hour ago"
        /// </summary>
        private readonly Regex _completeRelativeRegex = new Regex(@"^(?: *(\d) *(" + ValidUnits + ")s?)+( +ago)?$");
    
        public DateTime Parse(string input)
        {
            // Remove the case and trim spaces.
            input = input.Trim().ToLower();
    
            // Try common simple words like "yesterday".
            var result = TryParseCommonDateTime(input);
            if (result.HasValue)
                return result.Value;
    
            // Try common simple words like "last week".
            result = TryParseLastOrNextCommonDateTime(input);
            if (result.HasValue)
                return result.Value;
    
            // Try simple format like "+1 week".
            result = TryParseSimpleRelativeDateTime(input);
            if (result.HasValue)
                return result.Value;
    
            // Try first the full format like "1 day 2 hours 10 minutes ago".
            result = TryParseCompleteRelativeDateTime(input);
            if (result.HasValue)
                return result.Value;
    
            // Try parse fixed dates like "01/01/2000".
            return DateTime.Parse(input);
        }
    
        private static DateTime? TryParseCommonDateTime(string input)
        {
            switch (input)
            {
                case "now":
                    return DateTime.Now;
                case "today":
                    return DateTime.Today;
                case "tomorrow":
                    return DateTime.Today.AddDays(1);
                case "yesterday":
                    return DateTime.Today.AddDays(-1);
                default:
                    return null;
            }
        }
    
        private DateTime? TryParseLastOrNextCommonDateTime(string input)
        {
            var match = _basicRelativeRegex.Match(input);
            if (!match.Success)
                return null;
    
            var unit = match.Groups[2].Value;
            var sign = string.Compare(match.Groups[1].Value, "next", true) == 0 ? 1 : -1;
            return AddOffset(unit, sign);
        }
    
        private DateTime? TryParseSimpleRelativeDateTime(string input)
        {
            var match = _simpleRelativeRegex.Match(input);
            if (!match.Success)
                return null;
    
            var delta = Convert.ToInt32(match.Groups[1].Value);
            var unit = match.Groups[2].Value;
            return AddOffset(unit, delta);
        }
    
        private DateTime? TryParseCompleteRelativeDateTime(string input)
        {
            var match = _completeRelativeRegex.Match(input);
            if (!match.Success)
                return null;
    
            var values = match.Groups[1].Captures;
            var units = match.Groups[2].Captures;
            var sign = match.Groups[3].Success ? -1 : 1;
            Debug.Assert(values.Count == units.Count);
    
            var dateTime = UnitIncludeTime(units) ? DateTime.Now : DateTime.Today;
    
            for (int i = 0; i < values.Count; ++i)
            {
                var value = sign*Convert.ToInt32(values[i].Value);
                var unit = units[i].Value;
    
                dateTime = AddOffset(unit, value, dateTime);
            }
    
            return dateTime;
        }
    
        /// <summary>
        /// Add/Remove years/days/hours... to a datetime.
        /// </summary>
        /// <param name="unit">Must be one of ValidUnits</param>
        /// <param name="value">Value in given unit to add to the datetime</param>
        /// <param name="dateTime">Relative datetime</param>
        /// <returns>Relative datetime</returns>
        private static DateTime AddOffset(string unit, int value, DateTime dateTime)
        {
            switch (unit)
            {
                case "year":
                    return dateTime.AddYears(value);
                case "month":
                    return dateTime.AddMonths(value);
                case "week":
                    return dateTime.AddDays(value * 7);
                case "day":
                    return dateTime.AddDays(value);
                case "hour":
                    return dateTime.AddHours(value);
                case "minute":
                    return dateTime.AddMinutes(value);
                case "second":
                    return dateTime.AddSeconds(value);
                default:
                    throw new Exception("Internal error: Unhandled relative date/time case.");
            }
        }
    
        /// <summary>
        /// Add/Remove years/days/hours... relative to today or now.
        /// </summary>
        /// <param name="unit">Must be one of ValidUnits</param>
        /// <param name="value">Value in given unit to add to the datetime</param>
        /// <returns>Relative datetime</returns>
        private static DateTime AddOffset(string unit, int value)
        {
            var now = UnitIncludesTime(unit) ? DateTime.Now : DateTime.Today;
            return AddOffset(unit, value, now);
        }
    
        private static bool UnitIncludeTime(CaptureCollection units)
        {
            foreach (Capture unit in units)
                if (UnitIncludesTime(unit.Value))
                    return true;
            return false;
        }
    
        private static bool UnitIncludesTime(string unit)
        {
            switch (unit)
            {
                case "hour":
                case "minute":
                case "second":
                    return true;
    
                default:
                    return false;
            }
        }
    }
    

    I'm sure there are improvements possible but it should handle most cases in English. Please comment if you see improvements (like locale errors or such).

    EDIT: Fixed to be relative to now if the relative time includes time.

    0 讨论(0)
提交回复
热议问题