Конвертирование паттернов времени в DateTime

up_lvl

Client
Регистрация
02.09.2014
Сообщения
131
Благодарностей
52
Баллы
28
Существуют страницы в пределах одного домена на которых дата чего-либо(нунапример дата публикации поста) отображается по-разному в зависимости от давности публикации, юзерагента, прочих факторов. Эта дата является текстом по сути и нет никаких utc маркеров или стандартного паттерна в каком-нибудь аттрибуте/коде страницы. Посему возникает необходимость проверки и приведения такой даты-текста в формат дату-DateTime.

Необходима такая конструкция в OwnCodeUsings, которую можно было бы вызывать в кач-ве метода скормив ей паттерн даты-текста и получив на выходе дату-DateTime и которую можно расширять паттернами и обработчиками для них соответственно, набивая обойму для конвертирования так скажем.

Примеры текстовой даты
30 November 2017 at 11:27
2 hrs (типа 2 часа назад)
Yesterday at 12:20
 

Koqpe

Client
Регистрация
23.12.2014
Сообщения
1 100
Благодарностей
649
Баллы
113
Необходима такая конструкция в OwnCodeUsings, которую можно было бы вызывать в кач-ве метода скормив ей паттерн даты-текста и получив на выходе дату-DateTime и которую можно расширять паттернами и обработчиками для них соответственно, набивая обойму для конвертирования так скажем.
Какой бюджет?
 
  • Спасибо
Реакции: doc

up_lvl

Client
Регистрация
02.09.2014
Сообщения
131
Благодарностей
52
Баллы
28
По складывающейся традиции отвечаю сам себе

Код:
public static class DatePattern
    {
        private class RegexFunc
        {
            public Regex Pattern;
            public Func<string, DateTime> Converter;
        }
      
        private static class RegexFuncParsers
        {
            private static CultureInfo enCulture = new CultureInfo("en-US");
            private static DateTime nowTime { get { return DateTime.Now; } }
            public static RegexFunc[] DateParsers =
            {
                new RegexFunc //now
                    {
                        Pattern = new Regex("(?i)(now)"),
                        Converter = (string match) => nowTime
                    },
                new RegexFunc // (?i)\d+ min ago [5 mins]
                    {
                        Pattern = new Regex(@"(?i)^\d+.*?(?=min)"),
                        Converter = (string match) =>
                        {
                            string minutes = Regex.Match(match, @"(?i)^\d+.*?(?=min)").Value.Trim();
                            return nowTime.AddMinutes(0-int.Parse(minutes));
                        }
                    },
                new RegexFunc //(?i)\d+ hours ago [1 hour, 2hours, 1 hr, 2hrs]
                    {
                        Pattern = new Regex(@"(?i)^(\d+).*?(?=h(?:ou)?r)"),
                        Converter = (string match) =>
                        {
                            string hours = Regex.Match(match, @"(?i)^(\d+).*?(?=h(?:ou)?r)").Value.Trim();
                            return nowTime.AddHours(0-int.Parse(hours));
                        }
                    },
                new RegexFunc //(?i)today H/h:mm(?:\s?tt) [Today at 8:20 AM, Today at 8:20am, Today at 8:20]
                    {
                        Pattern = new Regex(@"(?i)^today.*?(\d+:\d+(?:\s?[apm]{2})?)$"),
                        Converter = (string match) =>
                        {
                            string tt = Regex.IsMatch(match, @"(?i)\d+:\d+(?:\s?[apm]{2})") ? "tt" : "";
                            string h = tt.Any<char>() ? "h" : "H";
                            match = Regex.Replace(match, @"(?i)^today.+?(?=\d+:)", "");
                            match = Regex.Replace(match, @"(?i)(?<=:\d.+)\s(?=[apm]{2})", ""); //delete space
                            match = DateTime.Today.ToString("yyyy MM dd ") + match;
                            string format = "yyyy MM dd " + h + ":mm" + tt;
                            return DateTime.ParseExact(match, format,  enCulture);
                        }
                    },
                new RegexFunc //(?i)yesterday H/h:mm(?:\s?tt) [Yesterday at 8:20 AM, Yesterday at 8:20am, Yesterday at 8:20]
                    {
                        Pattern = new Regex(@"(?i)^yesterday.*?(\d+:\d+(?:\s?[apm]{2})?)$"),
                        Converter = (string match) =>
                        {
                            string tt = Regex.IsMatch(match, @"(?i)\d+:\d+(?:\s?[apm]{2})") ? "tt" : "";
                            string h = tt.Any<char>() ? "h" : "H";
                            match = Regex.Replace(match, @"(?i)^yesterday.+?(?=\d+:)", "");
                            match = Regex.Replace(match, @"(?i)(?<=:\d.+)\s(?=[apm]{2})", ""); //delete space
                            match = DateTime.Today.AddDays(-1.0).ToString("yyyy MM dd ") + match;
                            string format = "yyyy MM dd " + h + ":mm" + tt;
                            return DateTime.ParseExact(match, format,  enCulture);
                        }
                    }
            };
        }
      
        public static DateTime Convert(string date_pattern)
        {
            date_pattern = date_pattern.Trim();
            var dateParsers = RegexFuncParsers.DateParsers;
            for (int i = 0; i < dateParsers.Length; i++)
            {
                var match = dateParsers[i].Pattern.Match(date_pattern);
                if (!match.Success)
                    continue;
                return dateParsers[i].Converter(date_pattern);
            }
            throw new Exception("no pattern in dateParsers for " + date_pattern);
        }
    }

Пример использования
Код:
var date_format = "yyyy-MM-dd HH:mm:ss.fff";
var date_pattern = "Yesterday at 12:43 PM";
var date = DatePattern.Convert(date_pattern).ToString(date_format);
return date;
 
  • Спасибо
Реакции: molotok и evgen_po

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)