Ежедневник IT-ка
133 subscribers
22 photos
4 videos
1 file
43 links
Программируем на практике!!
По вопросам по поводу проектов: @vladimir_dzen
Download Telegram
​​Работа со временем и датами - это одна из тех задач, которую необходимо делать в программирование очень часто. Ведь актуальность данных это, то на чём держится современный мир(ушёл от темы).
Мы также не будем отставать и будем работать со временем.

Задача: рассчитать среднее кол-во времени размещение постов в группе(наш случай) согласно сервиса telemetr.me .

Работаем в программном комплексе ZennoPoster, который отлично справляется с анализом структурой страницы.

1. Для того, чтобы получить все "времена длительности"(назовём это так), то мы должны понять в каком из тегов они находятся т.е. подготовить предварительные данные.
Из структуры страница сайта, мы понимаем, что вся нужная информация находится в одном главном для нас теге "tr". Находим его.

1.1. Обращаемся к свойству('ActiveTab') объекта('instance') и передаём полученную информацию в класс('Tab').

Tab tab = instance.ActiveTab;

instance - это объект, который позволяет получать информацию, которая находится в запущенном браузере(это очень грубое сравнение), но можно рассматривать и так.
Tab - это класс, который имеет свойства для работы с текущей вкладкой нашего браузера.

1.2. Получаем Все необходимые элементы, которые находятся в текущей вкладке нашего браузера, с помощью XPath запроса и передаём в класс('HtmlElementCollection' - который работает с группой элементов).

HtmlElementCollection entries = tab.FindElementsByXPath("//tr");

1.3. Если кол-во найденных элементов ('tr'), больше 0, то идём дальше.

1.4. Инициализируем переменные.

var lstTemp = new List<string>();
var totalTimePublicPostAdvertise = string.Empty;
var content = string.Empty;

if (entries.Count > 0)
{

1.5. Проходим в цикле по всем свойствам('InnerHtml'), полученных тегов tr, в которых и расположена нужная информация.

for (int x = 0; x < entries.Count; x++)
{
content = entries.Elements[x].InnerHtml;

1.6. ОБЯЗАТЕЛЬНО весь наш последующий
код должен быть расположен в
конструкции(try..catch), для того, чтобы при
возникновение ошибок, код понимал,
что делать в этом случае.

try{

1.7. Получаем информацию с необходимого тега('span' с названием класса 'kt-font-brand'), с помощью XPath запроса, используя метод ParseByXpath и сохраняем полученные данные в список.

lstTemp =
ZennoPoster.Parser.ParseByXpath(content,
"//span[contains(@class,'kt-font-brand')]",
"innerText").ToList();

totalTimePublicPostAdvertise =
lstTemp[0].Trim().Replace("'", @"''");

}catch (Exception ex){

1.8. Отправляем ошибку в лог ZennoPoster.

project.SendErrorToLog(ex.Message, true);
}
}

Продолжение следует...

#ZennoPoster, #Дата
Продолжаем работать со временем.
В прошлом примере, был получен список 'lstTemp' с временем.
Список выглядит так:

23 часов 58 минут,
23 часов 53 минут,
19 часов 9 минут,
23 часов 57 минут,
и т.д.

Наша цель преобразовать время, которое сейчас является типом данных "string" в тип данных "DateTime".
В C# существуют 2 метода(самые популярные), которые пытаются конвертировать "string" => "DateTime". Рассмотрим их более подробно.

1. DateTime.ParseExact(string s, string format, IFormatProvider? provider) - этот метод в качестве аргументов, кроме строки с датой, принимает еще строку в которой указан формат представления даты, а так же строку с указанием культуры, в которой принято такое представление.
Пример:

string time = "2021 Четверг октябрь 28 16:01";
System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CreateSpecificCulture("ru-RU");
DateTime dt = DateTime.ParseExact(time, "yyyy dddd MMMM dd HH:mm", culture);

Результат: 23.06.2020 14:35:00

2.DateTime.Parse(string s) - этот метод в качестве аргумента принимает строку с датой.
Пример:

string time = "23:58";
DateTime dt = = DateTime.Parse(time);

Результат: 28.10.2021 23:58:00

Методы существуют, но в нашем случае они не подходят т.к. не смогут распознать формат такого времени: "23 часов 58 минут".

Поэтому будет разбивать на определённые этапы:
1. Создаёт список с типом данных 'DateTime':

var listTimeTemp = new List<DateTime>();

2. Подготовим время в нормальный формат с помощью регулярного выражения, который поймёт метод: DateTime.Parse(string s):

tmpData = Regex.Replace(tmpData, @"ча.*?\s", ":");
tmpData = Regex.Replace(tmpData, @"мин.*", "");

после чистки, время уже будет иметь вот такой формат: "23:58"

3. Конвертируем и сохраняем полученное время в ранее созданный список 'listTimeTemp':

listTimeTemp.Add(DateTime.Parse(tmpData));

4. Сортируем полученное время в порядке возрастания с помощью 'Linq':

listTimeTemp.Sort((a, b) => a.CompareTo(b));

5. Создаёт список с типом данных 'double':

var totalMinutes = new List<double>();

6. Создаём цикл для списка 'listTimeTemp'( для того, чтобы получить минуты из часов и минуты из минут, соответственно. Формат времени из которого берутся эти данные:'28.10.2021 23:58:00'(пример)):

foreach (var hours in listTimeTemp)
{
int minutesFromHours = hours.Hour * 60;
int minutesFromMinutes = hours.Minute;
totalMinutes.Add(minutesFromHours + minutesFromMinutes);
}

7. Получаем среднюю сумму значения всех полученных минут из списка 'totalMinutes'.

var sum = totalMinutes.Sum() / listTimeTemp.Count;

8. Создаём объект 'TimeSpan', для того, чтобы из средней суммы, которую получили выше, получить часы и минуты:

TimeSpan ts = TimeSpan.FromMinutes(sum);
int midHours = ts.Hours;
int midMinutes = ts.Minutes;

9. Пример результата:

string res = ts.Hours.Tostring() + ":" + ts.Minutes.Tostring();

"22:52" - наше полученное искомое среднее время.

10. Пример всего кода:

var tmpData = string.Empty;
var listTimeTemp = new List<DateTime>();
for (x = 0; x < lstTemp.Count; x++)
{
tmpData = lstTemp[x].Trim();
tmpData = Regex.Replace(tmpData, @"ча.*?\s", ":");
tmpData = Regex.Replace(tmpData, @"мин.*", "");
listTimeTemp.Add(DateTime.Parse(tmpData));
}
listTimeTemp.Sort((a, b) => a.CompareTo(b));

var totalMinutes = new List<double>();
foreach (var hours in listTimeTemp)
{
int minutesFromHours = hours.Hour * 60;
int minutesFromMinutes = hours.Minute;
totalMinutes.Add(minutesFromHours +
minutesFromMinutes);
}
var sum = totalMinutes.Sum() / listTimeTemp.Count;
TimeSpan ts = TimeSpan.FromMinutes(sum);
int midHours = ts.Hours;
int midMinutes = ts.Minutes;
string res = ts.Hours.Tostring() + ":" + ts.Minutes.Tostring();

В этом примере рассмотрел те вещи, которые можно делать используя 'DateTime' и 'TimeSpan'.

#Csharp, #Дата