Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Посчет календарных промежутков между 2 датами, дней,европ, америк. недель, кварталов... 
:(
    Опции темы
leniviy
Дата 22.12.2010, 00:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 552
Регистрация: 8.2.2003
Где: Спб

Репутация: нет
Всего: 5



Делаю аццкий проект по агрегации данных. Есть желание сделать логику, чтобы можно было группировать не просто по год/месяц/день/час/минута, а, например, по 3*3 года, 10*35 дней и 2*5 часов.

Код

public class Aggregation {
    /** 
     * One of {@link java.util.Calendar} fields. Valid values: <ul>
     * <li/>{@link java.util.Calendar#YEAR}
     * <li/>{@link java.util.Calendar#MONTH}
     * <li/>{@link java.util.Calendar#DAY_OF_MONTH}
     * <li/>{@link java.util.Calendar#HOUR_OF_DAY}
     * <li/>{@link java.util.Calendar#MINUTE}
     * <li/>{@link java.util.Calendar#SECOND}
     * <li/>{@link java.util.Calendar#MILLISECOND}
     * </ul>
     */
    public int measure;
    /** non-negative number of e.g. hours in one period */
    public long measuresinperiod;
    /** non-negative number of periods to keep */
    public int periodstokeep;
}


Для этого надо текущую дату округлять до начала текущего/конца предыдущего периода. А чтобы это сделать, надо знать, сколько таких периодов прошло с какой-то начальной даты , например, 1970 года. И надо учитывать летнее время, високосные годы и т.д.

Функцию для подсчёта я написал, но может у кого есть вариант получше
Код

    private static void cal_addlong(Calendar cal, int field, long amount) {
        for (; amount > Integer.MAX_VALUE; amount -= Integer.MAX_VALUE) {
            cal.add(field, Integer.MAX_VALUE);
        }
        for (; amount < Integer.MIN_VALUE; amount += Integer.MAX_VALUE) {
            cal.add(field, Integer.MAX_VALUE);
        }
        cal.add(field, (int)amount);
    }
    
    private static long count(Date dstart, Date dend, int measure) {
        long ldstart = dstart.getTime();
        long ldend = dend.getTime();
        
        Calendar cal = Calendar.getInstance();

        // estimate number to add
        cal.setTimeInMillis(0);
        cal.add(measure, 1);
        long deltamin, deltamax, deltax;
        long measuresize = cal.getTimeInMillis();
        if (measuresize == 0) {
            deltamin = 0;
        } else {
            deltamin = (ldend - ldstart) / measuresize;
        }
        deltamax = deltamin + 1;

        int compmin, compmax, compx;
        
        // calculate initial range
        while(true) {
            int i;
            cal.setTime(dstart);
            cal_addlong(cal, measure, deltamin);
            compmin = (i = cal.getTime().compareTo(dend)) < 0 ? -1 : i > 0 ? 1 : 0;
            if (compmin == 0)
                return deltamin;
    
            cal.setTime(dstart);
            cal_addlong(cal, measure, deltamax);
            compmax = (i = cal.getTime().compareTo(dend)) < 0 ? -1 : i > 0 ? 1 : 0;
            if (compmax == 0)
                return deltamax;
            
            if (compmin != compmax)
                break;
            
            deltamin -= (Math.abs(deltamin) / 10 + 1); 
            deltamax += (Math.abs(deltamax) / 10 + 1); 
        }
        
        // bisect
        while(true) {
            int i;
            deltax = (deltamax + deltamin) / 2;
            if (deltax == deltamin || deltax == deltamax)
                break;
            cal.setTime(dstart);
            cal_addlong(cal, measure, deltamin);
            compmin = (i = cal.getTime().compareTo(dend)) < 0 ? -1 : i > 0 ? 1 : 0;
            if (compmin == 0)
                return deltamin;

            cal.setTime(dstart);
            cal_addlong(cal, measure, deltax);
            compx = (i = cal.getTime().compareTo(dend)) < 0 ? -1 : i > 0 ? 1 : 0;
            if (compx == 0)
                return deltax;
            
            if (compmin != compx) {
                deltamax = deltax;
            } else {
                cal.setTime(dstart);
                cal_addlong(cal, measure, deltamax);
                compmax = (i = cal.getTime().compareTo(dend)) < 0 ? -1 : i > 0 ? 1 : 0;
                if (compmax == 0)
                    return deltamax;
    
                if (compx == compmax)
                    break;
                
                deltamin = deltax;
            }
            
        }
        
        return Math.abs(deltamin) < Math.abs(deltamax) ? deltamin : deltamax;
    }


Это сообщение отредактировал(а) leniviy - 22.12.2010, 00:21
PM MAIL   Вверх
mgarin
Дата 25.12.2010, 22:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 19.8.2009
Где: Санкт-Петербург

Репутация: 1
Всего: 3



Может я конечно буду не прав...
Код
Для этого надо текущую дату округлять до начала текущего/конца предыдущего периода.

Не проще как-то так?:
Код
        Calendar cal = Calendar.getInstance ();
        cal.setTime ( new Date () );
        cal.set ( Calendar.DAY_OF_YEAR, 1 );
        cal.set ( Calendar.HOUR_OF_DAY, 1 );
        cal.set ( Calendar.MINUTE, 1 );
        cal.set ( Calendar.SECOND, 1 );
        cal.set ( Calendar.MILLISECOND, 1 );

Таким нехитрым образом вы получите время начала текущего года (ну это я к примеру привел).

Можете так же например откатывать время на 3 месяца:
Код
        Calendar cal = Calendar.getInstance ();
        cal.setTime ( new Date () );
        cal.set ( Calendar.MONTH, cal.get ( Calendar.MONTH ) - 3 );


Calendar сам все сделает за вас, даже если это будет 1ый месяц года - он переведет год на 1 назад и т.д.

Вариантов море. Думаю и то что Вы пытаетесь сделать можно сделать таким путем
Например в вашем случае Вы можете установить начальную дату и добавляя по 3 месяца (например) получить нужные промежутки

Либо, если я неправильно понял вопрос, извиняюсь...


Это сообщение отредактировал(а) mgarin - 25.12.2010, 22:14
PM MAIL WWW ICQ   Вверх
leniviy
Дата 25.12.2010, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 552
Регистрация: 8.2.2003
Где: Спб

Репутация: нет
Всего: 5



Цитата(mgarin @  25.12.2010,  22:12 Найти цитируемый пост)
Например в вашем случае Вы можете установить начальную дату и добавляя по 3 месяца (например) получить нужные промежутки

Вначале я так и делал, но проблемы начались с 1 апреля 1981 г.:
1 марта 1981 0:00
cal.add ( Calendar.MONTH, 1);
-> 1 апреля 1981 1:00
cal.add ( Calendar.MONTH, 1);
-> 1 мая 1981 1:00


Это сообщение отредактировал(а) leniviy - 25.12.2010, 22:40
PM MAIL   Вверх
mgarin
Дата 25.12.2010, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 19.8.2009
Где: Санкт-Петербург

Репутация: 1
Всего: 3



А вам именно так нужно увеличивать дату?
Через set по идее не должно появляться этой разницы в час (как мне кажется, не проверял)

Да и даже если появляется - всегда можно насильно сбросить в 0 - в чем проблема?)

Это сообщение отредактировал(а) mgarin - 25.12.2010, 22:45
PM MAIL WWW ICQ   Вверх
dorogoyIV
Дата 25.12.2010, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1503
Регистрация: 26.3.2007

Репутация: 3
Всего: 46



Цитата(leniviy @  25.12.2010,  22:40 Найти цитируемый пост)
Вначале я так и делал, но проблемы начались с 1 апреля 1981 г.:1 марта 1981 0:00cal.add ( Calendar.MONTH, 1);-> 1 апреля 1981 1:00cal.add ( Calendar.MONTH, 1);-> 1 мая 1981 1:00

как раз в марте перевод часов на летнее время. что бы это не сказывалось на программе, почитайте FAQ (была статья на этом форуме - ищите)

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0445 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.