From 8547f147463a26dee03e04cd1a3cd38208caea4b Mon Sep 17 00:00:00 2001 From: houcha Date: Thu, 20 May 2021 11:41:14 +0300 Subject: [PATCH] Upload solution --- .../AdventureTime/AdventureTime/Program.cs | 32 ++- .../AdventureTime/AdventureTime/Time.cs | 191 +++++++++++++----- 2 files changed, 166 insertions(+), 57 deletions(-) diff --git a/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Program.cs b/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Program.cs index af4efcae..79114770 100644 --- a/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Program.cs +++ b/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Program.cs @@ -1,9 +1,39 @@ -namespace AdventureTime +using System; + +namespace AdventureTime { internal class Program { private static void Main() { + DateTime dt = Time.WhatTimeIsIt(); + DateTime udt = Time.WhatTimeIsItInUtc(); + + Console.WriteLine(dt); + Console.WriteLine(udt); + + // all the same + Console.WriteLine(Time.SpecifyKind(dt, DateTimeKind.Utc)); + Console.WriteLine(Time.SpecifyKind(dt, DateTimeKind.Local)); + Console.WriteLine(Time.SpecifyKind(dt, DateTimeKind.Unspecified)); + + var roundtrip = Time.ToRoundTripFormatString(dt); + Console.WriteLine(roundtrip); + Console.WriteLine(Time.ParseFromRoundTripFormat(roundtrip)); + + Console.WriteLine(Time.AddTenSeconds(dt)); + Console.WriteLine(Time.AddTenSecondsV2(dt)); + + Console.WriteLine(Time.GetHoursBetween(udt, dt)); + Console.WriteLine(Time.GetTotalMinutesInThreeMonths()); + + Console.WriteLine(Time.GetAdventureTimeDurationInMinutes_ver0_Dumb()); + Console.WriteLine(Time.GetGenderSwappedAdventureTimeDurationInMinutes_ver0_Dumb()); + Console.WriteLine(Time.GetAdventureTimeDurationInMinutes_ver1_FeelsSmarter()); + Console.WriteLine(Time.GetAdventureTimeDurationInMinutes_ver3_NodaTime()); + + Console.WriteLine(Time.AreEqualBirthdays(dt, udt)); + Console.WriteLine(Time.AreEqualBirthdays(dt, udt.AddDays(1))); } } } diff --git a/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Time.cs b/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Time.cs index 45de70d1..c9c18a3a 100644 --- a/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Time.cs +++ b/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Time.cs @@ -14,7 +14,7 @@ internal static class Time /// public static DateTime WhatTimeIsIt() { - throw new NotImplementedException(); + return DateTime.Now; } /// @@ -22,7 +22,7 @@ public static DateTime WhatTimeIsIt() /// public static DateTime WhatTimeIsItInUtc() { - throw new NotImplementedException(); + return DateTime.UtcNow; } /// @@ -36,22 +36,28 @@ public static DateTime SpecifyKind(DateTime dt, DateTimeKind kind) /* Подсказка: поищи в статических методах DateTime. */ - throw new NotImplementedException(); + return DateTime.SpecifyKind(dt, kind); } /// - /// Конвертирует объект в эквивалентное ему строковое представление времени в формате ISO 8601 (aka round-trip format). + /// Конвертирует объект в эквивалентное ему + /// строковое представление времени в формате ISO 8601 (aka round-trip + /// format). /// /// Объект для конвертации в строку. /// Строковое представление времени в формате ISO 8601. public static string ToRoundTripFormatString(DateTime dt) { /* - Обязательно поиграйся и посмотри на изменение результата в зависимости от dt.Kind (для этого тебе поможет метод выше). - Ну и на будущее запомни этот прекрасный строковый формат представления времени - он твой бро! - Название запоминать не нужно, просто помни, что для передачи значения в виде строки, выбирать лучше инвариантные относительно сериализации/десериализации форматы. + Обязательно поиграйся и посмотри на изменение результата в + зависимости от dt.Kind (для этого тебе поможет метод выше). Ну + и на будущее запомни этот прекрасный строковый формат + представления времени - он твой бро! Название запоминать не + нужно, просто помни, что для передачи значения в виде строки, + выбирать лучше инвариантные относительно + сериализации/десериализации форматы. */ - throw new NotImplementedException(); + return dt.ToString("s", System.Globalization.CultureInfo.InvariantCulture); } /// @@ -62,10 +68,11 @@ Ну и на будущее запомни этот прекрасный стр public static DateTime ParseFromRoundTripFormat(string dtStr) { /* - Поиграйся и проверь, что round-trip действительно round-trip, т.е. туда-обратно равно оригиналу (для туда воспользуйся предыдущим методом). - Проверь для всех значений DateTime.Kind. + Поиграйся и проверь, что round-trip действительно round-trip, + т.е. туда-обратно равно оригиналу (для туда воспользуйся + предыдущим методом). Проверь для всех значений DateTime.Kind. */ - throw new NotImplementedException(); + return DateTime.Parse(dtStr, null, System.Globalization.DateTimeStyles.RoundtripKind); } /// @@ -74,10 +81,12 @@ Проверь для всех значений DateTime.Kind. public static DateTime ToUtc(DateTime dt) { /* - Eсли воспользуешься нужным методом, то напоминаю, что результат его работы зависит от dt.Kind. - В случае dt.Kind == Unspecified предполагается, что время локальное, т.е. результат работы в случае Local и Unspecified совпадают. Такие дела + Eсли воспользуешься нужным методом, то напоминаю, что результат + его работы зависит от dt.Kind. В случае dt.Kind == Unspecified + предполагается, что время локальное, т.е. результат работы в + случае Local и Unspecified совпадают. Такие дела */ - throw new NotImplementedException(); + return dt.ToUniversalTime(); } /// @@ -88,7 +97,7 @@ public static DateTime ToUtc(DateTime dt) public static DateTime AddTenSeconds(DateTime dt) { // здесь воспользуйся методами самого объекта и заодно посмотри какие еще похожие есть - throw new NotImplementedException(); + return dt.AddSeconds(10); } /// @@ -99,10 +108,13 @@ public static DateTime AddTenSeconds(DateTime dt) public static DateTime AddTenSecondsV2(DateTime dt) { /* - Ну а здесь воспользуйся сложением с TimeSpan. Обрати внимание, что помимо конструктора, у класса есть набор полезных статических методов-фабрик. - Обрати внимание, что у TimeSpan нет статических методов FromMonth, FromYear. Как думаешь, почему? + Ну а здесь воспользуйся сложением с TimeSpan. Обрати внимание, + что помимо конструктора, у класса есть набор полезных + статических методов-фабрик. Обрати внимание, что у TimeSpan нет + статических методов FromMonth, FromYear. Как думаешь, почему? */ - throw new NotImplementedException(); + var ten_sec = new TimeSpan(0, 0, 10); + return dt.Add(ten_sec); } /// @@ -118,7 +130,7 @@ public static int GetHoursBetween(DateTime dt1, DateTime dt2) 2) Проверь, учитывается ли Kind объектов при арифметических операциях. 3) Подумай, почему возвращаемое значение может отличаться от действительности. */ - throw new NotImplementedException(); + return Convert.ToInt32(Math.Abs((dt2 - dt1).TotalHours)); } /// @@ -127,7 +139,8 @@ public static int GetHoursBetween(DateTime dt1, DateTime dt2) public static int GetTotalMinutesInThreeMonths() { // ну тут все просто и очевидно, если сделал остальные и подумал над вопросами в комментах. - throw new NotImplementedException(); + var three_month = new TimeSpan(3*30, 0, 0, 0); + return Convert.ToInt32(three_month.TotalSeconds); } #region Adventure time saga @@ -136,27 +149,41 @@ public static int GetTotalMinutesInThreeMonths() /// Возвращает количество минут, проведенных в пути из Москвы в Лондон. /// /// - /// Финн и Джейк, плотно поужинав, решили, что спать для слабаков и настало время приключений, поэтому быстро собрали вещи, уложили спать БиМО и отправились из воображаемой Москвы в воображаемый Лондон верхом на леди Ливнероге. - /// Сколько минут они провели в пути, если Москву они покинули 28.03.2010 в 02:15 по местному времени, а в Лондон прибыли в 28.03.2010 в 02:15 по местному? + /// Финн и Джейк, плотно поужинав, решили, что спать для слабаков и + /// настало время приключений, поэтому быстро собрали вещи, уложили + /// спать БиМО и отправились из воображаемой Москвы в воображаемый + /// Лондон верхом на леди Ливнероге. Сколько минут они провели в пути, + /// если Москву они покинули 28.03.2010 в 02:15 по местному времени, а в + /// Лондон прибыли в 28.03.2010 в 02:15 по местному? /// public static int GetAdventureTimeDurationInMinutes_ver0_Dumb() { /* - Как ты понимаешь, время выбрано не просто так, но для начала давай прикинемся совсем наивными. - Лондон находится в часовом поясе +0 (GMT), а Москва в +3 (MSK). Воспользуйся DateTimeOffset, чтобы задать правильное время, и посчитай разницу в минутах. Посмотри на результат. - Держи, заготовочку для копипасты: + Как ты понимаешь, время выбрано не просто так, но для начала + давай прикинемся совсем наивными. Лондон находится в часовом + поясе +0 (GMT), а Москва в +3 (MSK). Воспользуйся + DateTimeOffset, чтобы задать правильное время, и посчитай + разницу в минутах. Посмотри на результат. Держи, заготовочку + для копипасты: - 2010, 3, 28, 2, 15, 0 */ - throw new NotImplementedException(); + var london_t = new DateTimeOffset(2010, 3, 28, 2, 15, 0, TimeSpan.FromHours(0)); + var moscow_t = new DateTimeOffset(2010, 3, 28, 2, 15, 0, TimeSpan.FromHours(3)); + + return Convert.ToInt32(Math.Abs((moscow_t - london_t).TotalMinutes)); } /// /// Возвращает количество минут, проведенных в пути из Москвы в Лондон. /// /// - /// Фионна и Кейк, поужинав заварными пироженками от принца Жвачки, решили, что они еще слишком молоды чтобы спать по ночам и сейчас самое время для приключений! Дамы собрали вещи, уложили спать БиМО и отправились из - /// другой воображаемой Москвы в другой воображаемый Лондон верхом на лорде Монохроме. - /// Сколько минут они провели в путешествии, если Москву они покинули 28.03.2010 в 03:15 по местному времени, а в Лондон прибыли в 28.03.2010 в 01:15 по местному? + /// Фионна и Кейк, поужинав заварными пироженками от принца Жвачки, + /// решили, что они еще слишком молоды чтобы спать по ночам и сейчас + /// самое время для приключений! Дамы собрали вещи, уложили спать БиМО и + /// отправились из другой воображаемой Москвы в другой воображаемый + /// Лондон верхом на лорде Монохроме. Сколько минут они провели в + /// путешествии, если Москву они покинули 28.03.2010 в 03:15 по местному + /// времени, а в Лондон прибыли в 28.03.2010 в 01:15 по местному? /// public static int GetGenderSwappedAdventureTimeDurationInMinutes_ver0_Dumb() { @@ -165,7 +192,10 @@ public static int GetGenderSwappedAdventureTimeDurationInMinutes_ver0_Dumb() - 2010, 3, 28, 3, 15, 0 - 2010, 3, 28, 1, 15, 0 */ - throw new NotImplementedException(); + var london_t = new DateTimeOffset(2010, 3, 28, 1, 15, 0, TimeSpan.FromHours(0)); + var moscow_t = new DateTimeOffset(2010, 3, 28, 3, 15, 0, TimeSpan.FromHours(3)); + + return Convert.ToInt32(Math.Abs((moscow_t - london_t).TotalMinutes)); } /// @@ -174,13 +204,22 @@ public static int GetGenderSwappedAdventureTimeDurationInMinutes_ver0_Dumb() public static int GetAdventureTimeDurationInMinutes_ver1_FeelsSmarter() { /* - Глава вторая, в которой оказывается, что в некоторых странах принята такая штука как летнее время (не совсем то, про которое поет Лана Дель Рей). - - Внимательный читатель мог усомниться в данных мной часовых поясах и их смещении относительно UTC и был бы прав. - На самом деле смещения таковы: Лондон +1 (BST - British Summer Time), Москва +4 (MSD - Moscow Daylight Time). - Давай теперь учтем правильное смещение. Я понимаю, что это очевидно, что результат не изменится, но тебе же не сложно скопипастить и просто поменять смещения? + Глава вторая, в которой оказывается, что в некоторых странах + принята такая штука как летнее время (не совсем то, про которое + поет Лана Дель Рей). + + Внимательный читатель мог усомниться в данных мной часовых + поясах и их смещении относительно UTC и был бы прав. На самом + деле смещения таковы: Лондон +1 (BST - British Summer Time), + Москва +4 (MSD - Moscow Daylight Time). Давай теперь учтем + правильное смещение. Я понимаю, что это очевидно, что результат + не изменится, но тебе же не сложно скопипастить и просто + поменять смещения? */ - throw new NotImplementedException(); + var london_t = new DateTimeOffset(2010, 3, 28, 1, 15, 0, TimeSpan.FromHours(1)); + var moscow_t = new DateTimeOffset(2010, 3, 28, 3, 15, 0, TimeSpan.FromHours(4)); + + return Convert.ToInt32(Math.Abs((moscow_t - london_t).TotalMinutes)); } // GetGenderSwappedAdventureTimeDurationInMinutes_ver1_FeelsSmarter опустим, там то же самое @@ -191,21 +230,39 @@ Внимательный читатель мог усомниться в дан public static int GetAdventureTimeDurationInMinutes_ver2_FeelsLikeRocketScience() { /* - Глава третья и последняя, в которой внезапно оказывается, что Финн и Фионна находятся в суперпозиции и существуют в виде гендерно нейтрального сверхчеловека, который и путешествовал из Москвы в Лондон. - - Дело в том, что перевод на летнее время в 2010м году в Москве произошел в 02:00 (стрелки часов перевели на час вперед), а в Лондоне - в 01:00. - Таким образом в Москве не было 02:15 - однако можно, например, считать, что этому времени соответствует 03:15. Ну а в Лондоне 01:15 это на самом деле 02:15. - Только как это обработать в рамках класса DateTimeOffset? Да, для конкретного примера мы могли бы сами ручками "перевести стрелки" и поставить правильное время, но что делать в общем случае? - Тут придется воспользоваться знанием о часовых поясах. Их есть у .Net. - - Дабы ты не мучился[-ась], роя в недрах msdn и stackoverflow в поисках ответа (в конце концов, когда тебе это в жизни действительно понадобится), - ниже ты найдешь готовый метод GetZonedTime. Просто посмотри на него (можешь даже посмотреть методы и свойства типа TimeZoneInfo, если интересно) и воспользуйся им для вычисления правильного времени - "отбытия" и "прибытия" наших героев. Затем посчитай длительность путешествия. Также даны правильные идентификаторы зон. + Глава третья и последняя, в которой внезапно оказывается, что + Финн и Фионна находятся в суперпозиции и существуют в виде + гендерно нейтрального сверхчеловека, который и путешествовал из + Москвы в Лондон. + + Дело в том, что перевод на летнее время в 2010м году в Москве + произошел в 02:00 (стрелки часов перевели на час вперед), а в + Лондоне - в 01:00. Таким образом в Москве не было 02:15 - + однако можно, например, считать, что этому времени соответствует + 03:15. Ну а в Лондоне 01:15 это на самом деле 02:15. Только как + это обработать в рамках класса DateTimeOffset? Да, для + конкретного примера мы могли бы сами ручками "перевести стрелки" + и поставить правильное время, но что делать в общем случае? Тут + придется воспользоваться знанием о часовых поясах. Их есть у + .Net. + + Дабы ты не мучился[-ась], роя в недрах msdn и stackoverflow в + поисках ответа (в конце концов, когда тебе это в жизни + действительно понадобится), ниже ты найдешь готовый метод + GetZonedTime. Просто посмотри на него (можешь даже посмотреть + методы и свойства типа TimeZoneInfo, если интересно) и + воспользуйся им для вычисления правильного времени "отбытия" и + "прибытия" наших героев. Затем посчитай длительность + путешествия. Также даны правильные идентификаторы зон. */ const string moscowZoneId = "Russian Standard Time"; const string londonZoneId = "GMT Standard Time"; - throw new NotImplementedException(); + var london_t = new DateTimeOffset(2010, 3, 28, 1, 15, 0, TimeSpan.FromHours(1)); + var moscow_t = new DateTimeOffset(2010, 3, 28, 3, 15, 0, TimeSpan.FromHours(4)); + + return Math.Abs(Convert.ToInt32(GetZonedTime(moscow_t.LocalDateTime, moscowZoneId) - + GetZonedTime(london_t.LocalDateTime, londonZoneId))); } /// @@ -214,11 +271,18 @@ ниже ты найдешь готовый метод GetZonedTime. Прост public static int GetGenderSwappedAdventureTimeDurationInMinutes_ver2_FeelsLikeRocketScience() { /* - Реши по аналогии с предыдущим методом и проверь, что оба метода действительно возвращают одно и то же время (и что оно правильное). + Реши по аналогии с предыдущим методом и проверь, что оба метода + действительно возвращают одно и то же время (и что оно + правильное). */ const string moscowZoneId = "Russian Standard Time"; const string londonZoneId = "GMT Standard Time"; - throw new NotImplementedException(); + + var london_t = new DateTimeOffset(2010, 3, 28, 1, 15, 0, TimeSpan.FromHours(0)); + var moscow_t = new DateTimeOffset(2010, 3, 28, 3, 15, 0, TimeSpan.FromHours(3)); + + return Convert.ToInt32(GetZonedTime(moscow_t.LocalDateTime, moscowZoneId) - + GetZonedTime(london_t.LocalDateTime, londonZoneId)); } private static DateTimeOffset GetZonedTime(DateTime localTime, string timeZoneId) @@ -232,7 +296,9 @@ private static DateTimeOffset GetZonedTime(DateTime localTime, string timeZoneId Console.WriteLine($"{localTime}: invalid = {isInvalid}; daylight = {isDaylightSaving}; ambigous = {isAmbiguous}"); - // несмотря на то, что DateTimeOffset хранит локальное время + смещение, в действительности здесь мы вычисляем правильное абсолютное значение (время UTC) + // несмотря на то, что DateTimeOffset хранит локальное время + + // смещение, в действительности здесь мы вычисляем правильное + // абсолютное значение (время UTC) return new DateTimeOffset(localTime, timeZone.GetUtcOffset(localTime)); } @@ -247,12 +313,18 @@ public static int GetAdventureTimeDurationInMinutes_ver3_NodaTime() const string londonTimeZoneId = "Europe/London"; const string moscowTimeZoneId = "Europe/Moscow"; - // Тип LocalDateTime не хранит информации о том, где "наблюдается" это время, но явно говорит, что данное время нужно трактовать как есть и никаких неявных преобразований не делать. - // Более того, его апи не позволяет тебе сделать что-то неявно или трактовать это время как-то иначе. Например, его невозможно превратить в абсолютное время UTC (в Noda Time ему отвечает тип Instant) + // Тип LocalDateTime не хранит информации о том, где "наблюдается" + // это время, но явно говорит, что данное время нужно трактовать как + // есть и никаких неявных преобразований не делать. Более того, его + // апи не позволяет тебе сделать что-то неявно или трактовать это + // время как-то иначе. Например, его невозможно превратить в + // абсолютное время UTC (в Noda Time ему отвечает тип Instant) var from = new LocalDateTime(2010, 3, 28, 2, 15, 0); var to = new LocalDateTime(2010, 3, 28, 2, 15, 0); - //Тип ZonedDateTime - это ровным счетом LocalDateTime + DateTimeZone (локальное время + часовой пояс). Вот из него абсолютное время уже можно получить (информации достаточно). + // Тип ZonedDateTime - это ровным счетом LocalDateTime + DateTimeZone + // (локальное время + часовой пояс). Вот из него абсолютное время уже + // можно получить (информации достаточно). var fromMoscowZoned = GetZonedTime(from, moscowTimeZoneId); var toLondonZoned = GetZonedTime(to, londonTimeZoneId); return (int) (toLondonZoned - fromMoscowZoned).TotalMinutes; @@ -260,10 +332,15 @@ public static int GetAdventureTimeDurationInMinutes_ver3_NodaTime() private static ZonedDateTime GetZonedTime(LocalDateTime localTime, string timeZoneId) { - // здесь используется не windows-specific словарь идентификаторов, а более "принятый" сообществом + // здесь используется не windows-specific словарь идентификаторов, а + // более "принятый" сообществом var timeZone = TzdbDateTimeZoneSource.Default.ForId(timeZoneId); - // обрати внимание, есть два метода, превращающих локальное время + часовой пояс в ZonedDateTime: InZoneLeniently и InZoneStrictly. Первый не ругается на сомнительное локальное время, второй - бросает исключение. Для наглядности конкретно этого примера я использовал "снисходительный" вариант. + // обрати внимание, есть два метода, превращающих локальное время + + // часовой пояс в ZonedDateTime: InZoneLeniently и InZoneStrictly. + // Первый не ругается на сомнительное локальное время, второй - + // бросает исключение. Для наглядности конкретно этого примера я + // использовал "снисходительный" вариант. return localTime.InZoneLeniently(timeZone); } @@ -277,7 +354,9 @@ private static ZonedDateTime GetZonedTime(LocalDateTime localTime, string timeZo /// True - если родились в один день, иначе - false. internal static bool AreEqualBirthdays(DateTime person1Birthday, DateTime person2Birthday) { - throw new NotImplementedException(); + return person1Birthday.Year == person2Birthday.Year && + person1Birthday.Month == person2Birthday.Month && + person1Birthday.Day == person2Birthday.Day; } } }