Создание, анализ ирефакторинг
Скачать 3.16 Mb.
|
393 136 /** Константа для воскресенья, эквивалент java.util.Calendar.SUNDAY. */ 137 public static final int SUNDAY = Calendar.SUNDAY; 138 139 /** Количество дней в месяцах невисокосного года. */ 140 static final int[] LAST_DAY_OF_MONTH = 141 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 142 143 /** Количество дней от начала года до конца месяца в невисокосном годе. */ 144 static final int[] AGGREGATE_DAYS_TO_END_OF_MONTH = 145 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; 146 147 /** Количество дней до конца предыдущего месяца. */ 148 static final int[] AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = 149 {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; 150 151 /** Количество дней от начала года до конца месяца в високосном годе. */ 152 static final int[] LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_MONTH = 153 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; 154 155 /** 156 * Количество дней до конца предыдущего месяца в високосном годе. 157 */ 158 static final int[] 159 LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = 160 {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; 161 162 /** Константа для обозначения первой недели месяца. */ 163 public static final int FIRST_WEEK_IN_MONTH = 1; 164 165 /** Константа для обозначения второй недели месяца. */ 166 public static final int SECOND_WEEK_IN_MONTH = 2; 167 168 /** Константа для обозначения третьей недели месяца. */ 169 public static final int THIRD_WEEK_IN_MONTH = 3; 170 171 /** Константа для обозначения четвертой недели месяца. */ 172 public static final int FOURTH_WEEK_IN_MONTH = 4; 173 174 /** Константа для обозначения последней недели месяца. */ 175 public static final int LAST_WEEK_IN_MONTH = 0; 176 177 /** Константа для обозначения типа диапазона. */ 178 public static final int INCLUDE_NONE = 0; 179 180 /** Константа для обозначения типа диапазона. */ 181 public static final int INCLUDE_FIRST = 1; 182 183 /** Константа для обозначения типа диапазона. */ 184 public static final int INCLUDE_SECOND = 2; 185 186 /** Константа для обозначения типа диапазона. */ продолжение 393 394 Приложение Б . org.jfree.date.SerialDate листинг Б .1 (продолжение) 187 public static final int INCLUDE_BOTH = 3; 188 189 /** 190 * Useful constant for specifying a day of the week relative to a fixed 191 * date. 192 */ 193 public static final int PRECEDING = -1; 194 195 /** 196 * Константа для определения дня недели относительно 197 * фиксированной даты. 198 */ 199 public static final int NEAREST = 0; 200 201 /** 202 * Константа для определения дня недели относительно 203 * фиксированной даты. 204 */ 205 public static final int FOLLOWING = 1; 206 207 /** Описание даты. */ 208 private String description; 209 210 /** 211 * Конструктор по умолчанию. 212 */ 213 protected SerialDate() { 214 } 215 216 /** 217 * Возвращает true , если целое число code соответствует218 * действительному дню недели, или false в противном случае.219 * 220 * @param code код, проверяемый на допустимость. 221 * 222 * @return true , если целое число code соответствует223 * действительному дню недели, false в противном случае.224 */ 225 public static boolean isValidWeekdayCode(final int code) { 226 227 switch(code) { 228 case SUNDAY: 229 case MONDAY: 230 case TUESDAY: 231 case WEDNESDAY: 232 case THURSDAY: 233 case FRIDAY: 234 case SATURDAY: 235 return true; 236 default: 394 org.jfree.date.SerialDate 395 237 return false; 238 } 239 240 } 241 242 /** 243 * Преобразует переданную строку в день недели. 244 * 245 * @param s строка, представляющая день недели. 246 * 247 * @return -1 , если строка не преобразуется, день недели248 * в противном случае. 249 */ 250 public static int stringToWeekdayCode(String s) { 251 252 final String[] shortWeekdayNames 253 = DATE_FORMAT_SYMBOLS.getShortWeekdays(); 254 final String[] weekDayNames = DATE_FORMAT_SYMBOLS.getWeekdays(); 255 256 int result = -1; 257 s = s.trim(); 258 for (int i = 0; i < weekDayNames.length; i++) { 259 if (s.equals(shortWeekdayNames[i])) { 260 result = i; 261 break; 262 } 263 if (s.equals(weekDayNames[i])) { 264 result = i; 265 break; 266 } 267 } 268 return result; 269 270 } 271 272 /** 273 * Возвращает строку, представляющую заданный день недели. 274 * 275 * Необходимо поискать более элегантное решение. 276 * 277 * @param weekday день недели. 278 * 279 * @return строка, представляющая заданный день недели. 280 */ 281 public static String weekdayCodeToString(final int weekday) { 282 283 final String[] weekdays = DATE_FORMAT_SYMBOLS.getWeekdays(); 284 return weekdays[weekday]; 285 286 } продолжение 395 396 Приложение Б . org.jfree.date.SerialDate листинг Б .1 (продолжение) 287 288 /** 289 * Возвращает массив названий месяцев. 290 * 291 * @return массив названий месяцев. 292 */ 293 public static String[] getMonths() { 294 295 return getMonths(false); 296 297 } 298 299 /** 300 * Возвращает массив названий месяцев. 301 * 302 * @param shortened флаг, указывающий на необходимость возврата 303 * сокращенных названий месяцев. 304 * 305 * @return массив названий месяцев. 306 */ 307 public static String[] getMonths(final boolean shortened) { 308 309 if (shortened) { 310 return DATE_FORMAT_SYMBOLS.getShortMonths(); 311 } 312 else { 313 return DATE_FORMAT_SYMBOLS.getMonths(); 314 } 315 316 } 317 318 /** 319 * Возвращает true, если целое число code соответствует действительному месяцу. 320 * 321 * @param code Код, проверяемый на действительность. 322 * 323 * @return true , если целое число code соответствует 324 * действительному месяцу. 325 */ 326 public static boolean isValidMonthCode(final int code) { 327 328 switch(code) { 329 case JANUARY: 330 case FEBRUARY: 331 case MARCH: 332 case APRIL: 333 case MAY: 334 case JUNE: 335 case JULY: 336 case AUGUST: 396 org.jfree.date.SerialDate 397 337 case SEPTEMBER: 338 case OCTOBER: 339 case NOVEMBER: 340 case DECEMBER: 341 return true; 342 default: 343 return false; 344 } 345 346 } 347 348 /** 349 * Возвращает квартал для заданного месяца. 350 * 351 * @param code код месяца (1-12). 352 * 353 * @return квартал, к которому относится месяц. 354 * @throws java.lang.IllegalArgumentException 355 */ 356 public static int monthCodeToQuarter(final int code) { 357 358 switch(code) { 359 case JANUARY: 360 case FEBRUARY: 361 case MARCH: return 1; 362 case APRIL: 363 case MAY: 364 case JUNE: return 2; 365 case JULY: 366 case AUGUST: 367 case SEPTEMBER: return 3; 368 case OCTOBER: 369 case NOVEMBER: 370 case DECEMBER: return 4; 371 default: throw new IllegalArgumentException( 372 "SerialDate.monthCodeToQuarter: invalid month code."); 373 } 374 375 } 376 377 /** 378 * Возвращает строку, представляющую заданный месяц. 379 * 380 * Строка возвращается в форме длинного названия месяца 381 * из локального контекста по умолчанию. 382 * 383 * @param month месяц. 384 * 385 * @return строка, представляющая заданный месяц. 386 */ продолжение 397 398 Приложение Б . org.jfree.date.SerialDate листинг Б .1 (продолжение) 387 public static String monthCodeToString(final int month) { 388 389 return monthCodeToString(month, false); 390 391 } 392 393 /** 394 * Возвращает строку, представляющую заданный месяц. 395 * 396 * Строка возвращается в форме длинного или короткого названия месяца 397 * из локального контекста по умолчанию. 398 * 399 * @param month месяц. 400 * @param shortened если true возвращает сокращенное401 * название месяца. 402 * 403 * @return строка, представляющая заданный месяц. 404 * @throws java.lang.IllegalArgumentException 405 */ 406 public static String monthCodeToString(final int month, 407 final boolean shortened) { 408 409 // Проверка аргументов... 410 if (!isValidMonthCode(month)) { 411 throw new IllegalArgumentException( 412 "SerialDate.monthCodeToString: month outside valid range."); 413 } 414 415 final String[] months; 416 417 if (shortened) { 418 months = DATE_FORMAT_SYMBOLS.getShortMonths(); 419 } 420 else { 421 months = DATE_FORMAT_SYMBOLS.getMonths(); 422 } 423 424 return months[month - 1]; 425 426 } 427 428 /** 429 * Преобразует строку в код месяца. 430 * 431 * Метод возвращает одну из констант JANUARY, FEBRUARY, ..., 432 * DECEMBER, соответствующую заданной строке. Если строка не распознается, 433 * метод возвращает -1. 434 * 435 * @param s строка для обработки. 436 * 398 org.jfree.date.SerialDate 399 437 * @return -1 , если строка не разбирается, месяц года438 * в противном случае. 439 */ 440 public static int stringToMonthCode(String s) { 441 442 final String[] shortMonthNames = DATE_FORMAT_SYMBOLS.getShortMonths(); 443 final String[] monthNames = DATE_FORMAT_SYMBOLS.getMonths(); 444 445 int result = -1; 446 s = s.trim(); 447 448 // Сначала пытаемся разобрать строку как целое число (1-12)... 449 try { 450 result = Integer.parseInt(s); 451 } 452 catch (NumberFormatException e) { 453 // Подавление 454 } 455 456 // Теперь ищем по названиям месяцев... 457 if ((result < 1) || (result > 12)) { 458 for (int i = 0; i < monthNames.length; i++) { 459 if (s.equals(shortMonthNames[i])) { 460 result = i + 1; 461 break; 462 } 463 if (s.equals(monthNames[i])) { 464 result = i + 1; 465 break; 466 } 467 } 468 } 469 470 return result; 471 472 } 473 474 /** 475 * Возвращает true, если целое число code представляет действительную 476 * неделю месяца, или false в противном случае. 477 * 478 * @param code код, проверяемый на действительность. 479 * @return true , если целое число code представляет 480 * действительную неделю месяца. 481 */ 482 public static boolean isValidWeekInMonthCode(final int code) { 483 484 switch(code) { 485 case FIRST_WEEK_IN_MONTH: 486 case SECOND_WEEK_IN_MONTH: 487 case THIRD_WEEK_IN_MONTH: продолжение 399 400 Приложение Б . org.jfree.date.SerialDate листинг Б .1 (продолжение) 488 case FOURTH_WEEK_IN_MONTH: 489 case LAST_WEEK_IN_MONTH: return true; 490 default: return false; 491 } 492 493 } 494 495 /** 496 * Определяет, является ли заданный год високосным. 497 * 498 * @param yyyy год (в диапазоне от 1900 до 9999). 499 * 500 * @return true , если заданный код является високосным.501 */ 502 public static boolean isLeapYear(final int yyyy) { 503 504 if ((yyyy % 4) != 0) { 505 return false; 506 } 507 else if ((yyyy % 400) == 0) { 508 return true; 509 } 510 else if ((yyyy % 100) == 0) { 511 return false; 512 } 513 else { 514 return true; 515 } 516 517 } 518 519 /** 520 * Возвращает количество високосных годов от 1900 до заданного года 521 * ВКЛЮЧИТЕЛЬНО. 522 * 523 * Учтите, что 1900 год високосным не является. 524 * 525 * @param yyyy год (в диапазоне от 1900 до 9999). 526 * 527 * @return количество високосных годов от 1900 до заданного года. 528 */ 529 public static int leapYearCount(final int yyyy) { 530 531 final int leap4 = (yyyy - 1896) / 4; 532 final int leap100 = (yyyy - 1800) / 100; 533 final int leap400 = (yyyy - 1600) / 400; 534 return leap4 - leap100 + leap400; 535 536 } 537 400 org.jfree.date.SerialDate 401 538 /** 539 * Возвращает номер последнего дня месяца с учетом 540 * високосных годов. 541 * 542 * @param month месяц. 543 * @param yyyy год (в диапазоне от 1900 до 9999). 544 * 545 * @return номер последнего дня месяца. 546 */ 547 public static int lastDayOfMonth(final int month, final int yyyy) { 548 549 final int result = LAST_DAY_OF_MONTH[month]; 550 if (month != FEBRUARY) { 551 return result; 552 } 553 else if (isLeapYear(yyyy)) { 554 return result + 1; 555 } 556 else { 557 return result; 558 } 559 560 } 561 562 /** 563 * Создает новую дату, прибавляя заданное количество дней 564 * к базовой дате. 565 * 566 * @param days количество прибавляемых дней (может быть отрицательным). 567 * @param base базовая дата. 568 * 569 * @return новая дата. 570 */ 571 public static SerialDate addDays(final int days, final SerialDate base) { 572 573 final int serialDayNumber = base.toSerial() + days; 574 return SerialDate.createInstance(serialDayNumber); 575 576 } 577 578 /** 579 * Создает новую дату, прибавляя заданное количество месяцев 580 * к базовой дате. 581 * 582 * Если базовая дата близка к концу месяца, результат может слегка 583 * смещаться: 31 мая + 1 месяц = 30 июня 584 * 585 * @param months количество прибавляемых месяцев (может быть отрицательным). 586 * @param base базовая дата. 587 * продолжение 401 402 Приложение Б . org.jfree.date.SerialDate листинг Б .1 (продолжение) 588 * @return новая дата. 589 */ 590 public static SerialDate addMonths(final int months, 591 final SerialDate base) { 592 593 final int yy = (12 * base.getYYYY() + base.getMonth() + months - 1) 594 / 12; 595 final int mm = (12 * base.getYYYY() + base.getMonth() + months - 1) 596 % 12 + 1; 597 final int dd = Math.min( 598 base.getDayOfMonth(), SerialDate.lastDayOfMonth(mm, yy) 599 ); 600 return SerialDate.createInstance(dd, mm, yy); 601 602 } 603 604 /** 605 * Создает новую дату, прибавляя заданное количество лет 606 * к базовой дате. 607 * 608 * @param years количество прибавляемых лет (может быть отрицательным). 609 * @param base базовая дата. 610 * 611 * @return новая дата. 612 */ 613 public static SerialDate addYears(final int years, final SerialDate base) { 614 615 final int baseY = base.getYYYY(); 616 final int baseM = base.getMonth(); 617 final int baseD = base.getDayOfMonth(); 618 619 final int targetY = baseY + years; 620 final int targetD = Math.min( 621 baseD, SerialDate.lastDayOfMonth(baseM, targetY) 622 ); 623 624 return SerialDate.createInstance(targetD, baseM, targetY); 625 626 } 627 628 /** 629 * Возвращает последнюю дату, приходящуюся на заданный день недели, 630 * ПРЕДШЕСТВУЮЩУЮ базовой дате. 631 * 632 * @param targetWeekday код дня недели. 633 * @param base базовая дата. 634 * 635 * @return последняя дата, приходящаяся на заданный день недели, 636 * ПРЕДШЕСТВУЮЩАЯ базовой дате. 637 */ 402 org.jfree.date.SerialDate 403 638 public static SerialDate getPreviousDayOfWeek(final int targetWeekday, 639 final SerialDate base) { 640 641 // Проверить аргументы... 642 if (!SerialDate.isValidWeekdayCode(targetWeekday)) { 643 throw new IllegalArgumentException( 644 "Invalid day-of-the-week code." 645 ); 646 } 647 648 // Определить дату... 649 final int adjust; 650 final int baseDOW = base.getDayOfWeek(); 651 if (baseDOW > targetWeekday) { 652 adjust = Math.min(0, targetWeekday - baseDOW); 653 } 654 else { 655 adjust = -7 + Math.max(0, targetWeekday - baseDOW); 656 } 657 658 return SerialDate.addDays(adjust, base); 659 660 } 661 662 /** 663 * Возвращает самую раннюю дату, приходящуюся на заданный день недели 664 * ПОСЛЕ базовой даты. 665 * 666 * @param targetWeekday код дня недели. 667 * @param base базовая дата. 668 * 669 * @return самая ранняя дата, приходящаяся на заданный день недели 670 * ПОСЛЕ базовой даты. 671 */ 672 public static SerialDate getFollowingDayOfWeek(final int targetWeekday, 673 final SerialDate base) { 674 675 // Проверить аргументы... 676 if (!SerialDate.isValidWeekdayCode(targetWeekday)) { 677 throw new IllegalArgumentException( 678 "Invalid day-of-the-week code." 679 ); 680 } 681 682 // Определить дату... 683 final int adjust; 684 final int baseDOW = base.getDayOfWeek(); 685 if (baseDOW > targetWeekday) { 686 adjust = 7 + Math.min(0, targetWeekday - baseDOW); 687 } 688 else { продолжение 403 404 Приложение Б . org.jfree.date.SerialDate листинг Б .1 (продолжение) 689 adjust = Math.max(0, targetWeekday - baseDOW); 690 } 691 692 return SerialDate.addDays(adjust, base); 693 } 694 695 /** 696 * Возвращает дату, приходящуюся на заданный день недели, 697 * САМУЮ БЛИЗКУЮ к базовой дате. 698 * 699 * @param targetDOW код дня недели. 700 * @param base базовая дата. 701 * 702 * @return дата, приходящаяся на заданный день недели, 703 * САМАЯ БЛИЗКАЯ к базовой дате. 704 */ 705 public static SerialDate getNearestDayOfWeek(final int targetDOW, 706 final SerialDate base) { 707 708 // Проверить аргументы... 709 if (!SerialDate.isValidWeekdayCode(targetDOW)) { 710 throw new IllegalArgumentException( 711 "Invalid day-of-the-week code." 712 ); 713 } 714 715 // Определить дату... 716 final int baseDOW = base.getDayOfWeek(); 717 int adjust = -Math.abs(targetDOW - baseDOW); 718 if (adjust >= 4) { 719 adjust = 7 - adjust; 720 } 721 if (adjust <= -4) { 722 adjust = 7 + adjust; 723 } 724 return SerialDate.addDays(adjust, base); 725 726 } 727 728 /** 729 * Перемещает дату к последнему дню месяца. 730 * 731 * @param base базовая дата. 732 * 733 * @return новая дата. 734 */ 735 public SerialDate getEndOfCurrentMonth(final SerialDate base) { 736 final int last = SerialDate.lastDayOfMonth( 737 base.getMonth(), base.getYYYY() 738 ); 404 |