Nano Hash - криптовалюты, майнинг, программирование

Datetime - получить следующий вторник

Как я могу узнать дату следующего вторника?

В PHP это так же просто, как strtotime('next tuesday');.

Как я могу добиться чего-то подобного в .NET

14.06.2011

  • ASP.NET - это набор веб-технологий. C # - это язык. Вам действительно нужно думать об этом с точки зрения простого .NET. Теперь, в следующий вторник - это первый вторник после сегодняшнего? Если бы это был понедельник, и кто-то сказал бы, что увидимся в следующий вторник, я бы ожидал, что это будет означать 8 дней, а не 1. А что, если сегодня вторник? Какое время суток вам нужно? 14.06.2011
  • Если сегодня вторник, вы хотите узнать дату следующего вторника? Или сегодня понедельник, вы хотите найти второй вторник с понедельника? 14.06.2011
  • Ближайший вторник, к какому-либо конкретному дню. 14.06.2011
  • @brenjtL: А если уже вторник? 14.06.2011
  • Если уже вторник, то в тот же день 14.06.2011

Ответы:


1

Как я уже упоминал в комментариях, под «следующим вторником» можно понимать разные вещи, но этот код дает вам «следующий вторник или сегодня, если уже вторник»:

DateTime today = DateTime.Today;
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysUntilTuesday = ((int) DayOfWeek.Tuesday - (int) today.DayOfWeek + 7) % 7;
DateTime nextTuesday = today.AddDays(daysUntilTuesday);

Если вы хотите выделить «неделю», если уже вторник, вы можете использовать:

// This finds the next Monday (or today if it's Monday) and then adds a day... so the
// result is in the range [1-7]
int daysUntilTuesday = (((int) DayOfWeek.Monday - (int) today.DayOfWeek + 7) % 7) + 1;

... или вы можете использовать исходную формулу, но с завтрашнего дня:

DateTime tomorrow = DateTime.Today.AddDays(1);
// The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
int daysUntilTuesday = ((int) DayOfWeek.Tuesday - (int) tomorrow.DayOfWeek + 7) % 7;
DateTime nextTuesday = tomorrow.AddDays(daysUntilTuesday);

РЕДАКТИРОВАТЬ: Просто чтобы сделать это красивым и универсальным:

public static DateTime GetNextWeekday(DateTime start, DayOfWeek day)
{
    // The (... + 7) % 7 ensures we end up with a value in the range [0, 6]
    int daysToAdd = ((int) day - (int) start.DayOfWeek + 7) % 7;
    return start.AddDays(daysToAdd);
}

Итак, чтобы получить значение «сегодня или в следующие 6 дней»:

DateTime nextTuesday = GetNextWeekday(DateTime.Today, DayOfWeek.Tuesday);

Чтобы получить значение «следующий вторник, кроме сегодняшнего»:

DateTime nextTuesday = GetNextWeekday(DateTime.Today.AddDays(1), DayOfWeek.Tuesday);
14.06.2011
  • Ух ты, мне просто было интересно, как я могу получить n дней до следующего вторника, а затем ты обновил свой ответ примером Nice. Спасибо 14.06.2011
  • Трудно было выбрать правильный ответ. Но ваш вариант кажется наиболее универсальным, и вы облегчили его понимание. Спасибо за помощь. 14.06.2011
  • @brenjt: На самом деле я бы сказал, что Sven более универсален, так как вы можете указать день недели, но это ваш выбор :) (я теперь отредактировал свой, чтобы дать более обобщенную версию.) 14.06.2011
  • Однако решение +7)%7 довольно хорошее. Хотя причина, по которой я не использовал это, заключается в том, что это небольшая микро-оптимизация и слишком легко ошибиться (а также жертвовать некоторой читабельностью), imho, конечно. 14.06.2011
  • Модульный тест: [TestMethod] public void ShouldGetNextSaturday () {var now = DateTime.Now; var test = GetNextWeekday (DateTime.Today, DayOfWeek.Saturday); Assert.IsTrue (now.Day ‹test.Day, ожидаемого числа месяца здесь нет.); Assert.IsTrue (test.DayOfWeek == DayOfWeek.Saturday, ожидаемого дня недели здесь нет.); Assert.IsTrue ((test.Day - now.Day) ‹7, ожидаемого интервала дней здесь нет.); } 11.01.2012
  • @rasx: Плохой модульный тест - не сработает к концу месяца, когда это может быть (скажем) 30-го числа, а в следующую субботу - 2-е. (Я вообще не люблю использовать сегодняшнюю дату в модульных тестах - мне нравится, чтобы тесты повторялись.) Также предполагается, что дата не переключается между оценкой DateTime.Now и DateTime.Today. 11.01.2012
  • @Jon: отличные наблюдения! ... кстати, какую платформу для модульного тестирования .NET вы предпочитаете? Кроме того, вы рекомендуете какие-либо книги или письменные документы по модульному тестированию? 30.01.2012
  • @rasx: Я лично использую NUnit просто потому, что он всегда делает то, что мне нужно, иногда с небольшой помощью. Это не значит, что он лучший :) Честно говоря, я не читал много книг о модульном тестировании. 30.01.2012

  • 2

    Это должно помочь:

    static DateTime GetNextWeekday(DayOfWeek day)
    {
        DateTime result = DateTime.Now.AddDays(1);
        while( result.DayOfWeek != day )
            result = result.AddDays(1);
        return result;
    }
    
    14.06.2011
  • Отличный ответ, если сегодня вторник (а это ха), вернется ли это сегодня или в следующий вторник? 14.06.2011
  • Это вернется в следующий вторник. Если вы хотите, чтобы он вернулся сегодня, просто удалите .AddDays(1) из первой строки, так он также проверит сам DateTime.Now. 14.06.2011

  • 3

    Есть менее подробные и более умные / элегантные решения этой проблемы, но следующая функция C # действительно хорошо работает для ряда ситуаций.

    /// <summary>
    /// Find the closest weekday to the given date
    /// </summary>
    /// <param name="includeStartDate">if the supplied date is on the specified day of the week, return that date or continue to the next date</param>
    /// <param name="searchForward">search forward or backward from the supplied date. if a null parameter is given, the closest weekday (ie in either direction) is returned</param>
    public static DateTime ClosestWeekDay(this DateTime date, DayOfWeek weekday, bool includeStartDate = true, bool? searchForward=true)
    {
        if (!searchForward.HasValue && !includeStartDate) 
        {
            throw new ArgumentException("if searching in both directions, start date must be a valid result");
        }
        var day = date.DayOfWeek;
        int add = ((int)weekday - (int)day);
        if (searchForward.HasValue)
        {
            if (add < 0 && searchForward.Value)
            {
                add += 7;
            }
            else if (add > 0 && !searchForward.Value)
            {
                add -= 7;
            }
            else if (add == 0 && !includeStartDate)
            {
                add = searchForward.Value ? 7 : -7;
            }
        }
        else if (add < -3) 
        {
            add += 7; 
        }
        else if (add > 3)
        {
            add -= 7;
        }
        return date.AddDays(add);
    }
    
    25.01.2013
  • Единственный ответ, который реализуется как расширение DateTime. В то время как все остальные решения работают, использование его в качестве метода расширения дает самый простой в использовании код. 06.11.2018

  • 4

    @Jon Skeet хороший ответ.

    За предыдущий день:

    private DateTime GetPrevWeekday(DateTime start, DayOfWeek day) {
        // The (... - 7) % 7 ensures we end up with a value in the range [0, 6]
        int daysToRemove = ((int) day - (int) start.DayOfWeek - 7) % 7;
        return start.AddDays(daysToRemove);
    }
    

    Спасибо!!

    07.01.2015
  • Обратите внимание, что это решение включает отрицательные числа, переданные оператору по модулю. В статье в Википедии об операторе по модулю говорится, что Если a или n отрицательны, наивное определение не работает, и языки программирования различаются по способу определения этих значений. Хотя это, вероятно, работает в C #, математически более «надежным» решением для получения того же результата было бы поменять местами DayOfWeek значения следующим образом: int daysToSubtract = -(((int)dateTime.DayOfWeek - (int)day + 7) % 7); 09.05.2016

  • 5

    Очень простой образец для включения или исключения текущей даты, вы указываете дату и день недели, которые вас интересуют.

    public static class DateTimeExtensions
    {
        /// <summary>
        /// Gets the next date.
        /// </summary>
        /// <param name="date">The date to inspected.</param>
        /// <param name="dayOfWeek">The day of week you want to get.</param>
        /// <param name="exclDate">if set to <c>true</c> the current date will be excluded and include next occurrence.</param>
        /// <returns></returns>
        public static DateTime GetNextDate(this DateTime date, DayOfWeek dayOfWeek, bool exclDate = true)
        {
            //note: first we need to check if the date wants to move back by date - Today, + diff might move it forward or backwards to Today
            //eg: date - Today = 0 - 1 = -1, so have to move it forward
            var diff = dayOfWeek - date.DayOfWeek;
            var ddiff = date.Date.Subtract(DateTime.Today).Days + diff;
    
            //note: ddiff < 0 : date calculates to past, so move forward, even if the date is really old, it will just move 7 days from date passed in
            //note: ddiff >= (exclDate ? 6 : 7) && diff < 0 : date is into the future, so calculated future weekday, based on date
            if (ddiff < 0 || ddiff >= (exclDate ? 6 : 7) && diff < 0)
                diff += 7; 
    
            //note: now we can get safe values between 0 - 6, especially if past dates is being used
            diff = diff % 7;
    
            //note: if diff is 0 and we are excluding the date passed, we will add 7 days, eg: 1 week
            diff += diff == 0 & exclDate ? 7 : 0;
    
            return date.AddDays(diff);
        }
    }
    

    некоторые тестовые примеры

    [TestMethod]
        public void TestNextDate()
        {
            var date = new DateTime(2013, 7, 15);
            var start = date;
            //testing same month - forwardOnly
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday)); //16
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday)); //17
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Thursday)); //18
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Friday)); //19
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Saturday)); //20
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Sunday)); //21
            Assert.AreEqual(start.AddDays(1), date.GetNextDate(DayOfWeek.Monday)); //22
    
            //testing same month - include date
            Assert.AreEqual(start = date, date.GetNextDate(DayOfWeek.Monday, false)); //15
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday, false)); //16
            Assert.AreEqual(start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday, false)); //17
    
            //testing month change - forwardOnly
            date = new DateTime(2013, 7, 29);
            start = date;
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday)); //30
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday)); //31
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Thursday)); //2013/09/01-month increased
            Assert.AreEqual(start.AddDays(1), date.GetNextDate(DayOfWeek.Friday)); //02
    
            //testing year change
            date = new DateTime(2013, 12, 30);
            start = date;
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Tuesday)); //31
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Wednesday)); //2014/01/01 - year increased
            Assert.AreEqual(start = start.AddDays(1), date.GetNextDate(DayOfWeek.Thursday)); //02
        }
    
    07.03.2019
  • Я внес дополнительные изменения в исходный ответ после обширного тестирования. Теперь это будет безопасно рассчитывать следующий день на основе использованной даты, прошлого, настоящего и будущего. Все предыдущие примеры были хорошими, но не удались при определенных условиях. Я не делал это однострочным заявлением, чтобы можно было сделать дополнительные комментарии к тому, что делают вычисления. Положительный случай Джона Скита был великолепен, хотя случай, который у меня был, заключался в том, чтобы переместиться на 1 день назад с даты, но все же больше, чем сегодня, и что, если он переместится на сегодня или на вчера ... это решило проблему. 13.03.2019

  • 6

    Теперь в единственном вкусе - на случай, если вам нужно передать его как параметр в какой-то механизм.

    DateTime.Now.AddDays(((int)yourDate.DayOfWeek - (int)DateTime.Now.DayOfWeek + 7) % 7).Day
    

    В этом конкретном случае:

    DateTime.Now.AddDays(((int)DayOfWeek.Tuesday - (int)DateTime.Now.DayOfWeek + 7) % 7).Day
    
    07.01.2016

    7

    Это может быть и расширением, все зависит от

    public static class DateTimeExtensions
    {
        public static IEnumerable<DateTime> Next(this DateTime date, DayOfWeek day)
        {
            // This loop feels expensive and useless, but the point is IEnumerable
            while(true)
            {
                if (date.DayOfWeek == day)
                {
                    yield return date;
                }
                date = date.AddDays(1);
            }
        }
    }
    

    использование

        var today = DateTime.Today;
        foreach(var monday in today.Next(DayOfWeek.Monday))
        {
            Console.WriteLine(monday);
            Console.ReadKey();
        }
    
    15.02.2017
  • Возврат доходности в цикле без предложения выхода кажется немного рискованным. 15.07.2021

  • 8

    Версия цели C:

    +(NSInteger) daysUntilNextWeekday: (NSDate*)startDate withTargetWeekday: (NSInteger) targetWeekday
    {
        NSInteger startWeekday = [[NSCalendar currentCalendar] component:NSCalendarUnitWeekday fromDate:startDate];
        return (targetWeekday - startWeekday + 7) % 7;
    }
    
    28.08.2017
  • Классный ответ, но исходный вопрос задан про .NET. 15.11.2017

  • 9
  • Если сегодня понедельник, то ответ, который вы предоставили, даст неделю со вторника, а не завтра. 01.11.2014
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..