Есть две даты. Как создать список интервалов месяцев между этими датами?

Вы можете использовать .replace. Например:

>>> df = pd.DataFrame({'col2': {0: 'a', 1: 2, 2: np.nan}, 'col1': {0: 'w', 1: 1, 2: 2}})
>>> di = {1: "A", 2: "B"}
>>> df
  col1 col2
0    w    a
1    1    2
2    2  NaN
>>> df.replace({"col1": di})
  col1 col2
0    w    a
1    A    2
2    B  NaN

или непосредственно на Series, то есть df["col1"].replace(di, inplace=True).

-1
задан sadrutdin.zainukov 16 January 2019 в 22:02
поделиться

2 ответа

Вы должны действительно использовать java.time API, есть некоторые интересные вещи, используя

class MonthInterval {

    static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");

    LocalDateTime monthBegin, monthEnd;

    public MonthInterval(LocalDateTime monthBegin, LocalDateTime monthEnd) {
        this.monthBegin = monthBegin;
        this.monthEnd = monthEnd;
    }

    @Override
    public String toString() {
        return monthBegin.format(formatter) + " > " + monthEnd.format(formatter);
    }
}

Вы можете делать разные способы, например

  1. С помощью [115 ]

    static List<MonthInterval> list(LocalDateTime begin, LocalDateTime end) {
        List<MonthInterval> list = new ArrayList<>();
        LocalDateTime nextDayMonth;
        do {
            nextDayMonth = begin.plusMonths(1).withDayOfMonth(1);
            list.add(new MonthInterval(begin, nextDayMonth));
            begin = nextDayMonth;
        } while (nextDayMonth.getMonthValue() != end.getMonthValue());
        list.add(new MonthInterval(begin, end));
        return list;
    }
    
  2. С петлей for-i

    static List<MonthInterval> list(LocalDateTime begin, LocalDateTime end) {
        List<MonthInterval> list = new ArrayList<>();
        LocalDateTime nextDayMonth;
        for (int i = 0; i < ChronoUnit.MONTHS.between(begin, end) + 1; i++) {
            nextDayMonth = begin.plusMonths(1).withDayOfMonth(1);
            list.add(new MonthInterval(begin, nextDayMonth));
            begin = nextDayMonth;
        }
        list.add(new MonthInterval(begin, end));
        return list;
    }
    

Для использования в качестве

static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");

public static void main(String[] args) {
    LocalDateTime begin = LocalDateTime.parse("21.01.2018 00:00", formatter);
    LocalDateTime end = LocalDateTime.parse("20.03.2018 00:00", formatter);
    list(begin, end).forEach(System.out::println);
}

// And get
21.01.2018 00:00 > 01.02.2018 00:00
01.02.2018 00:00 > 01.03.2018 00:00
01.03.2018 00:00 > 20.03.2018 00:00
0
ответ дан azro 16 January 2019 в 22:02
поделиться

tl; dr

Interval.of(
    LocalDateTime.parse(                                    // Represent a date and a time-of-day but lacking a time zone or offset-from-UTC. So *not* a moment.
        "21.01.2018 00:00" ,
        DateTimeFormatter.ofPattern( "dd.MM.uuuu HH:mm" )   // Specify formatting pattern to match input strings.
    )                                                       // Returns a `LocalDateTime` object.
    .atZone(                                                // Apply a time zone to determine a moment.
        ZoneId.of( "Pacific/Auckland" )                     // Always use proper time zone in `Continent/Region` format, never 2-4 letter codes such as `IST` or `EST` or `PST`.
    )                                                       // Returns a `ZonedDateTime` object.
    .toInstant() ,                                          // Convert from a `ZonedDateTime` object to a `Instant` to adjust into UTC.
    …                                                       // Do the same as the above (the starting point) but for the stopping point.
)                                                           // Returns a `org.threeten.extra.Interval` object.
.toString()                                                 // Generate text representing both moments of this interval in standard ISO 8601 format, delimited by a `/` SOLIDUS character.

Избегайте устаревших классов даты и времени

Никогда не используйте java.util.Date. Этот ужасный класс был вытеснен несколько лет назад современными java.time классами.

ThreeTen-Extra

Другой ответ от azro направлен в правильном направлении. Но нет необходимости изобретать свой собственный интервальный класс. Посмотрите на существующие проверенные классы, найденные в проекте ThreeTen-Extra . Этот проект возглавляет тот же человек, Стивен Колебурн, который возглавлял проект JSR 310 java.time и Joda-Time .

В библиотеке ThreeTen-Extra вы найдете два класса для представления промежутка времени, прикрепленного к временной шкале.

  • Interval - пара моментов в UTC, Instant объектов.
  • LocalDateRange - пара значений только для даты, LocalDate объектов.

Моменты

Если вы имели в виду моменты, проанализируйте ваши входные строки в LocalDateTime объектах. Это не моменты, а только потенциальные моменты, поскольку у них нет часового пояса или смещения от UTC.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd.MM.uuuu HH:mm" ) ;
LocalDateTime ldt = LocalDateTime.parse( "21.01.2018 00:00" , f ) ;

Придайте этим LocalDateTime реальное значение, назначив часовой пояс для определения фактического момента.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;

Настройте UTC, извлекая Instant. Instant представляет момент всегда в UTC.

Instant instant = zdt.toInstant() ;

Передайте пару таких Instant объектов, чтобы получить Interval.

org.threeten.extra.Interval interval = Interval.of( start , stop ) ;

Вы можете сравнить Interval объекты с удобными методами, такими как isBefore, isAfter, overlaps, contains, encloses и т. Д.

Даты

Если вы сосредотачиваетесь только на датах, а не на моментах, используйте LocalDateRange. Мы все еще должны обработать ваши входные данные, как показано выше, так как дата меняется по всему миру в любой данный момент. Например, через несколько минут после полуночи в Париже Франция - это «завтра», а еще «вчера» в Монреале-Квебеке.

Для дат возьмите объекты ZonedDateTime, показанные выше, и извлеките LocalDate.

LocalDate ld = zdt.toLocalDate() ;  // Extract the date as seen at that moment through the wall-clock time used by the people of that region (that time zone).

Сделайте LocalDateRange с такими датами

org.threeten.extra.LocalDateRange ldr = LocalDateRange.of( start , stop ) ;

Как и Interval, класс LocalDateRange предлагает удобные методы сравнения, такие как overlaps, contains, и т.д.

Полуоткрытое

21.01.2018 00:00 - 01.02.2018 00:00 (или 31.01.2018 23:59:59)

Нет , не определяйте промежуток времени по его последнему возможному моменту. Это неловко и проблематично. Одна проблема - это бесконечно делимая дробная секунда.

Вместо этого используйте метод Half-Open : начало - включительно , а окончание - эксклюзивно .

Поиск переполнения стека для более подробной информации.


О java.time

Среда java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые унаследованные классы даты и времени, такие как java.util.Date , Calendar и amp; [1 148] SimpleDateFormat [1 148].

Проект Joda-Time , который теперь находится в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация: JSR 310 .

Вы можете обмениваться объектами java.time непосредственно с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где взять классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval , YearWeek , YearQuarter и еще . ]

0
ответ дан Basil Bourque 16 January 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: