Пример A-8. days-between: Подсчет числа дней между двумя датами | Популярный Linux

Опубликовано Bash в Ср, 23/12/2009 — 21:13

Пример A-8. days-between: Подсчет числа дней между двумя датами

  1. #!/bin/bash
  2. # days-between.sh:    Подсчет числа дней между двумя датами.
  3. # Порядок использования: ./days-between.sh [M]M/[D]D/YYYY [M]M/[D]D/YYYY
  4. ARGS=2                # Ожидается два аргумента из командной строки.
  5. E_PARAM_ERR=65        # Ошибка в числе ожидаемых аргументов.
  6. REFYR=1600            # Начальный год.
  7. CENTURY=100
  8. DIY=365
  9. ADJ_DIY=367           # Корректировка на високосный год + 1.
  10. MIY=12
  11. DIM=31
  12. LEAPCYCLE=4
  13. MAXRETVAL=255         # Максимально возможное возвращаемое значение
  14.                       # для положительных чисел.
  15. diff=                         # Количество дней между датами.
  16. value=                # Абсолютное значение.
  17. day=                  # день, месяц, год.
  18. month=
  19. year=
  20. Param_Error ()        # Ошибка в пвраметрах командной строки.
  21. {
  22.   echo «Порядок использования: `basename $0` [M]M/[D]D/YYYY [M]M/[D]D/YYYY»
  23.   echo »       (даты должны быть после 1/3/1600)»
  24.   exit $E_PARAM_ERR
  25. }
  26. Parse_Date ()                 # Разбор даты.
  27. {
  28.   month=${1%%/**}
  29.   dm=${1%/**}                 # День и месяц.
  30.   day=${dm#*/}
  31.   let «year = `basename $1`«  # Хотя это и не имя файла, но результат тот же.
  32. }
  33. check_date ()                 # Проверка даты.
  34. {
  35.   [ «$day« -gt «$DIM« ] || [ «$month« -gt «$MIY« ] || [ «$year« -lt «$REFYR« ] && Param_Error
  36.   # Выход из сценария при обнаружении ошибки.
  37.   # Используется комбинация «ИЛИ-списка / И-списка».
  38.   #
  39.   # Упражнение: Реализуйте более строгую проверку даты.
  40. }
  41. strip_leading_zero () # Удалить ведущий ноль
  42. {
  43.   val=${1#0}          # иначе Bash будет считать числа
  44.   return $val         # восьмеричными (POSIX.2, sect 2.9.2.1).
  45. }
  46. day_index ()          # Формула Гаусса:
  47. {                     # Количество дней от 3 Янв. 1600 до заданной даты.
  48.   day=$1
  49.   month=$2
  50.   year=$3
  51.   let «month = $month — 2″
  52.   if [ «$month« -le 0 ]
  53.   then
  54.     let «month += 12»
  55.     let «year -= 1»
  56.   fi
  57.   let «year -= $REFYR«
  58.   let «indexyr = $year / $CENTURY«
  59.   let «Days = $DIY*$year + $year/$LEAPCYCLE$indexyr + $indexyr/$LEAPCYCLE + $ADJ_DIY*$month/$MIY + $day$DIM«
  60.   # Более подробное объяснение алгоритма вы найдете в
  61.   # <a href=»http://home.t-online.de/home/berndt.schwerdtfeger/cal.htm
  62. » title=»http://home.t-online.de/home/berndt.schwerdtfeger/cal.htm
  63. «>http://home.t-online.de/home/berndt.schwerdtfeger/cal.htm
  64. </a>  if [ «$Days» -gt «$MAXRETVAL» ]  # Если больше 255,
  65.  then                             # то поменять знак
  66.    let «dindex = 0$Days»       # чтобы функция смогла вернуть полное значение.
  67.  else let «dindex = $Days«
  68.  fi
  69.  return $dindex
  70. }
  71. calculate_difference ()            # Разница между двумя датами.
  72. {
  73.  let «diff = $1$2»             # Глобальная переменная.
  74. }
  75. abs ()                             # Абсолютное значение
  76. {                                  # Используется глобальная переменная «value«.
  77.  if [ «$1» -lt 0 ]                # Если число отрицательное
  78.  then                             # то
  79.    let «value = 0$1»           # изменить знак,
  80.  else                             # иначе
  81.    let «value = $1»               # оставить как есть.
  82.  fi
  83. }
  84. if [ $# -ne «$ARGS» ]              # Требуется два аргумента командной строки.
  85. then
  86.  Param_Error
  87. fi
  88. Parse_Date $1
  89. check_date $day $month $year      # Проверка даты.
  90. strip_leading_zero $day           # Удалить ведущие нули
  91. day=$?                            # в номере дня и/или месяца.
  92. strip_leading_zero $month
  93. month=$?
  94. day_index $day $month $year
  95. date1=$?
  96. abs $date1                         # Абсолютное значение
  97. date1=$value
  98. Parse_Date $2
  99. check_date $day $month $year
  100. strip_leading_zero $day
  101. day=$?
  102. strip_leading_zero $month
  103. month=$?
  104. day_index $day $month $year
  105. date2=$?
  106. abs $date2                         # Абсолютное значение
  107. date2=$value
  108. calculate_difference $date1 $date2
  109. abs $diff                          # Абсолютное значение
  110. diff=$value
  111. echo $diff
  112. exit 0
  113. # Сравните этот сценарий с реализацией формулы Гаусса на C
  114. # http://buschencrew.hypermart.net/software/datedif

Запись опубликована в рубрике Без рубрики. Добавьте в закладки постоянную ссылку.