2015-05-03 2 views
1

Мне нужно найти момент, который находится в середине месяца. Вместо того, чтобы заниматься целыми месяцами, мне нужна середина месяца и середина следующего месяца. FYI, прецедент предназначен для рисования диаграмм, затенения каждой стороны начала каждого месяца по временной шкале; но это не имеет значения.Найдите середину месяца

Целых дней было бы достаточно хорошее разрешение. Очевидно, что месяцы не все имеют четное количество дней, но допустимое правило, например «первые 15 дней», будет приемлемым. Однако мне нужно будет указать значения даты-времени, такие как DateTime в Joda-Time.

В настоящее время я использую ± 15 дней в качестве произвольной строки для середины месяца. Что-то вроде следующего.

DateTime target = DateTime.now(DateTimeZone.forID("Africa/Casablanca")) ; 
DateTime monthStart = target.withDayOfMonth(1).withTimeAtStartOfDay() ; 
DateTime halfMonthPast = monthStart.minusDays(15) ; 
DateTime halfMonthCurrent = monthStart.plusDays(15) ; 
Interval halfAndHalf = new Interval(halfMonthPast , halfMonthCurrent) ; 

Но произвольно использование 15 дней вызывает перекрытия или пробелы в месяцах без 30 дней. Я предпочел бы рассчитать точную среднюю точку, поэтому серия этих интервалов будет аккумулировать друг друга аккуратно без зазоров или перекрытий. В идеале будет использоваться подход Half-Open, поэтому начало будет включено, а окончание - исключительно.

[mid-April to mid-May][mid-May to mid-June][mid-June to mid-July]

Используя либо Joda-Time или java.time будет предпочтительным маршрутом.

+0

У вас есть код, показывающий вам первоначальные попытки? –

+0

Можете ли вы поделиться некоторым кодом, который может продемонстрировать, чего именно вы пытаетесь достичь? –

+0

Пожалуйста, определите, что именно вы ожидаете. Если вы сообщите нам, что ожидаемый ответ будет за 30-дневный месяц и 31-дневный месяц, это должно быть достаточно хорошим (мы можем выяснить февраль). – ajb

ответ

3

Необходимо найти общее количество дней в месяце, а затем найти среднюю дату месяца.

Это также зависит от того, хотите ли вы 15-го или 16-го числа стать мидтадом в течение 31 месяца.

int iYear = 2015; //Substitue for current year 
int iMonth = Calendar.FEBRUARY; // Substitute for month 
int iDay = 1; 

// Create a calendar object and set year and month 
Calendar mycal = new GregorianCalendar(iYear, iMonth, iDay); 

// Get the number of days in that month 
int daysInMonth = mycal.getActualMaximum(Calendar.DAY_OF_MONTH); // 28 

//Use this if you want 15th to be mid date for a month of 31 days) 
int midDay= (daysInMonth) /2 ; 
//Use this if you want 16th to be mid date for a month of 31 days) 
int midDay = (int)Math.ceil(((double)daysInMonth)/2); 

Calendar mycal = new GregorianCalendar(iYear, iMonth, midDay); 
1

а) Если вы пишете

Целые дни будет достаточно хорошее разрешение.

я рекомендую использования LocalDate для любого промежуточного расчета не DateTime (Joda-Time) или ZonedDateTime (Java 8). В конце вы всегда можете преобразовать LocalDate в глобальную метку времени, если хотите. Это позволяет использовать Joda-Time-класс Interval с датами, преобразованными в глобальные временные метки. Java-8 не предлагает класс Interval. Вы можете использовать Threeten-Extra, который имеет простой интервал реализации. К сожалению, в обеих библиотеках отсутствует класс интервалов дат.

Однако, написание такого упрощенного интервала дат вам легко (см. Также, как простая реализация интервала в Thriten-Extra). Вам нужна только одна дата в месяц. Таким образом, вы можете использовать такую ​​дату, как дата начала, включительно для предыдущего интервала, и ту же дату, что и дата окончания, для следующего интервала от полутора до полугода. Использование глобальных временных меток почти всегда является ненужным сложным шагом в таких сценариях, связанных только с датами, включая любые вычисления часовых поясов (но, конечно, возможно использование выражений типа toDateTimeAtStartOfDay(zone) в Joda-Time).

b) Окончательный ответ полностью зависит от того, как вы определяете середину месяца.Либо вы всегда выбираете пятнадцатый или шестнадцатый или она зависит от длины месяца, который вы можете получить так:

Joda Время:

LocalDate jd = new LocalDate(2012, 2, 7); 
System.out.println(jd.dayOfMonth().getMaximumValue()); // 29 

Java-8 (рекомендуется автором Joda-Time):

LocalDate d8 = LocalDate.of(2012, 2, 7); 
System.out.println(d8.lengthOfMonth()); // 29 

Затем вы можете использовать формулы, как, например, (здесь Java-8-код):

LocalDate halfMonth = LocalDate.of(year, month, lengthOfMonth()/2 + 1);