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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Нахождение возраста по дате рождения, Оптимальный вариант 
V
    Опции темы
Kizja
Дата 23.3.2010, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Привет, кто-нибудь может предложить более короткий вариант нахождения возраста по дате рождения, чем следующий:

Код

public int getAge() {
    long currentDate = new Date().getTime();
    long birthDate = getBirthDate().getTime();
        
    Date age = new Date(currentDate - birthDate);

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy");
        
    return new Integer(formatter.format(age)).intValue() - 1970;
}


Если рассматривать этот вариант, то кроме всего прочего ещё хотел бы избавиться от захардкоденного "1970" и заменить его на что-то более вразумительное, но не убогое типа создание даты и вытаскивания из неё года: 
Код
new Date(1,1,1970).getYear()
 

или как-то так smile 

Хотя он вообще уже deprecated.

Может вообще уже такая функция где-то есть, а я сейчас изобретаю велосипед?
PM MAIL   Вверх
MaxPayneC
Дата 23.3.2010, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Моя реализация:
Код

    /**
     * Метод возвращает возраст человека.
     *
     * @param birthDate Дата рождения человека.
     * @return Возраст человека.
     */
    public static int getAge(Date birthDate)
    {
        Calendar birth = Calendar.getInstance();
        birth.setTime(birthDate);
        Calendar today = Calendar.getInstance();
        int age = today.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
        if (today.get(Calendar.DAY_OF_YEAR) <= birth.get(Calendar.DAY_OF_YEAR))
        {
            age--;
        }

        return age;
    }

PM   Вверх
Kizja
Дата 23.3.2010, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



MaxPayneC, круто, этот вариант очень понравился, а главное ничего лишнего... От тебя всегда поступают хорошие решения - помню ты про сортировку мапы тоже хороший вариант подкинул smile 

Думаю лучшего решения в данном случае уже никто предложить не сможет...
PM MAIL   Вверх
ivanovpv
Дата 23.3.2010, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


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

Репутация: 4
Всего: 28



А если так?

Код

public int getAge(Date birthDate) 
{
    final static long yearmillis=365*24*3600*1000;
    long current = new Date().getTime();
    long birth = birthDate.getTime();

    return (int )(current-birth)/yearmillis;
}


Тут есть проблема с високосными годами... Но ИМХО это не даст ошибку - все равно при округлении это будет нивелировано.


--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
intr
Дата 23.3.2010, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



А так еще красивее smile
Код

Years.yearsBetween(new LocalDate(1983, 7, 9), new LocalDate()).getYears()

Но тогда надо использовать дополнительную библиотеку joda-time - http://joda-time.sourceforge.net/
--------------------
Исследователь бытия и по совместительству Java-developer
PM MAIL WWW Skype GTalk   Вверх
Kizja
Дата 23.3.2010, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



ivanovpv, да, выглядит покороче того варианта, что привёл MaxPayneC, но считает в данный момент не совсем правильно - мой возраст например определил в 557 лет (это хоть и всего на пару лет, но больше, чем на самом деле smile ). Конечно же понятно, что это можно исправить или возможно даже я единственный, кто такой старый, но сам факт того, что здесь происходят всякие математические расчёты (умножение/деление) может способствовать возникновению ошибок... Захардкоденные цифорки, как и в приведённом мною первом варианте, - это не совсем в тему, т.е. я лично всеми возможными способами стараюсь избавляться от не совсем очевидных цифр. Плюс ещё как ты сам подметил бага с високосным годом... Мне кажется всё таки вариант MaxPayneC лучше, хотя это всего лишь моё мнение...

intr, да, этот вариант тоже хорош своей краткостью, но я бы наверное к нему бы прибегнул именно в том случае, если эта библиотека уже подключена, поскольку в противном случае из-за 1-го маленького метода подключать всю библиотеку не хочется - т.е. это очевидный минус в данном случае...

В варианте MaxPayneC я вобщем-то не вижу минусов, поэтому лично мне по прежнему больше всего по душе именно тот вариант...

Это сообщение отредактировал(а) Kizja - 23.3.2010, 18:23
PM MAIL   Вверх
MaxPayneC
Дата 23.3.2010, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Вариант, который предложил ivanovpv, возможно бажит, если человек родился до 1970 года или если сейчас больше, чем максимальное юникс-время... 2030й год, что ли... не помню точно, когда количество секунд перестанет в 32 бита помещаться.
PM   Вверх
Kizja
Дата 23.3.2010, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Я не подился до 1970 года, но сейчас бажит всё равно smile
PM MAIL   Вверх
jk1
Дата 23.3.2010, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 40
Всего: 75



Бажит по двум причинам:
1) Переполнение типа, вместо
Код

 final static long yearmillis=365*24*3600*1000;

нужно
Код

 final static long yearmillis=365*24*3600*1000L;


2) ошибка в приведении типа, вместо
Код

 return (int )(current-birth)/yearmillis;

нужно
Код

 return (int)((current-birth)/yearmillis);



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
LSD
Дата 23.3.2010, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15719
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(ivanovpv @  23.3.2010,  17:44 Найти цитируемый пост)
Но ИМХО это не даст ошибку - все равно при округлении это будет нивелировано.

Даст на пограничных днях (например день следующий за днем рождения).


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
intr
Дата 23.3.2010, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Кстати, вариант предложенный @MaxPayneC может дать ошибку если время указывается с точностью до миллисекунды smile Хотя возможно это не критично smile

А  joda-time крайне полезная библиотека, да и у нее нет зависимостей на другие либыsmile
--------------------
Исследователь бытия и по совместительству Java-developer
PM MAIL WWW Skype GTalk   Вверх
Kizja
Дата 23.3.2010, 21:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Я думаю "с точностью до миллисекунды" ещё ни один человек свой день рождения не отмечал smile
PM MAIL   Вверх
intr
Дата 24.3.2010, 03:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Kizja @ 24.3.2010,  02:39)
Я думаю "с точностью до миллисекунды" ещё ни один человек свой день рождения не отмечал smile

Та же проблема с минутами, секундами и часами smile 
--------------------
Исследователь бытия и по совместительству Java-developer
PM MAIL WWW Skype GTalk   Вверх
ivanovpv
Дата 24.3.2010, 09:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


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

Репутация: 4
Всего: 28



Цитата(jk1 @  23.3.2010,  18:47 Найти цитируемый пост)
Бажит по двум причинам:
1) Переполнение типа

Да, согласен - так и надо
Цитата(jk1 @  23.3.2010,  18:47 Найти цитируемый пост)

2) ошибка в приведении типа, вместо

а вот тут не согласен, операция cast имеет наименьший приоритет, так что кастироваться будет после выполнения всех операций с правой стороны

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

Код MaxPayneC безусловно самый правильный, мне он тоже нравится, хотя привлечение тяжелого класса Calendar немного напрягает - в этом смысле он мало чем отличается от кода intr где вместо класса Calendar используется библиотека joda-time.

Решать какой код лучше - не моя задача. Если бы решал, я - посмотрел сначала на требования: если код для какого-нибудь телефона или кард-аппарата, остался бы с кодом ivanovpv, а если обычное консольно-вебное приложение - тут и думать не надо - код MaxPayneC - самое оно.


--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
jk1
Дата 24.3.2010, 09:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

Репутация: 40
Всего: 75



Цитата

а вот тут не согласен, операция cast имеет наименьший приоритет, так что кастироваться будет после выполнения всех операций с правой стороны

Это не так, операция приведения типа имеет довольно высокий приоритет, выше только ++, --, ~ и !. Чтобы не быть голословным, приведу пример:
Код

        Date birthDate = new Date(90,10,10);
        long yearmillis = 365 * 24 * 3600 * 1000L;
        long current = new Date().getTime();
        long birth = birthDate.getTime();
       System.out.println((int) (current - birth) / yearmillis);    // выводит 0
       System.out.println((int) ((current - birth) / yearmillis));  // выводит 19



--------------------
Opinions are like assholes — everybody has one
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.0654 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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