A = "2002-20-10"
B = "2003-22-11"
Як знайти різницю в днях між двома датами?
A = "2002-20-10"
B = "2003-22-11"
Як знайти різницю в днях між двома датами?
Відповіді:
Якщо у вас GNU date, це дозволяє надрукувати подання довільної дати ( -dопція). У цьому випадку перетворіть дати в секунди після EPOCH, відніміть і поділіть на 24 * 3600.
Або вам потрібен портативний спосіб?
echo "( `date -d $B +%s` - `date -d $A +%s`) / (24*3600)" | bc -l
Баш-спосіб - перетворіть дати у формат% y% m% d, а потім ви можете зробити це прямо з командного рядка:
echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) ))
%y%m%dформаті. Наприклад, дата gnu приймає %Y-%m-%dформат, який використовується OP. Загалом, ISO-8601 є хорошим вибором (і формат OP - один із таких форматів). Форматів із двозначними роками краще уникати.
days_diff=$(( (`date -d $B +%s` - `date -d "00:00" +%s`) / (24*3600) )). зауважте, що $days_diffце буде ціле число (тобто без десяткових знаків)
dateвстановленого. Це працює для GNU date. Це не працює з POSIX date. Це, мабуть, не є проблемою для більшості читачів, але варто зазначити.
%Y-%m-%d , поки ми не введемо August 2.0і October 2.0формат OP є %Y-%d-%m. Відповідний xkcd: xkcd.com/1179
tl; д-р
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s)) / (60*60*24) ))
Стережись! Багато баш-рішень тут розбиті на діапазони дат, які охоплюють дату, коли починається перехід на літній час (де це можливо). Це пов’язано з тим, що конструкція $ ((math)) виконує операцію «підлога» / усікання отриманого значення, повертаючи лише ціле число. Дозвольте проілюструвати:
Перехід на літній та зимовий час розпочався 8 березня цього року в США, тому давайте використаємо діапазон дат, який охоплює таке:
start_ts=$(date -d "2015-03-05" '+%s')
end_ts=$(date -d "2015-03-11" '+%s')
Давайте подивимося, що ми отримаємо в подвійних дужках:
echo $(( ( end_ts - start_ts )/(60*60*24) ))
Повертає "5".
Роблячи це, використовуючи 'bc' з більшою точністю, ми отримуємо інший результат:
echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc
Повертає "5,95" - відсутність 0,05 є втратою години від переходу на літній час.
То як це слід робити правильно?
Я б запропонував використовувати замість цього:
printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)
Тут "printf" округлює більш точний результат, розрахований за допомогою "bc", даючи нам правильний діапазон дат "6".
Редагувати: виділити відповідь у коментарі @ hank-schultz нижче, який я використовую останнім часом:
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))
Це також повинно бути другим безпечним стрибком, якщо ви завжди віднімаєте попередню дату від пізнішої, оскільки високосні секунди лише збільшують різницю - скорочення фактично округлюється до правильного результату.
echo $(( ($(date --date="2015-03-11 UTC" +%s) - $(date --date="2015-03-05 UTC" +%s) )/(60*60*24) ))яка повертає 6, а не 5.
І в python
$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398
bashі shell, тому, я думаю, ми можемо припустити, що мова йде про систему * nix. У таких системах, echoі dateдостовірно присутній, але пітон немає.
Це працює для мене:
A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days
Відбитки
398 days
Що відбувається?
date -dдля обробки рядків часуdate %sдля перетворення часових рядків у секунди з 1970 року (епоха Unix)Якщо опція -d працює у вашій системі, ось ще один спосіб це зробити. Існує застереження, що це не буде враховувати високосних років, оскільки я розглядав 365 днів на рік.
date1yrs=`date -d "20100209" +%Y`
date1days=`date -d "20100209" +%j`
date2yrs=`date +%Y`
date2days=`date +%j`
diffyr=`expr $date2yrs - $date1yrs`
diffyr2days=`expr $diffyr \* 365`
diffdays=`expr $date2days - $date1days`
echo `expr $diffyr2days + $diffdays`
Ось версія MAC OS X для вашої зручності.
$ A="2002-20-10"; B="2003-22-11";
$ echo $(((`date -jf %Y-%d-%m $B +%s` - `date -jf %Y-%d-%m $A +%s`)/86400))
радість!
A="2002-20-10"; B="2003-22-11"
echo $(((`date -jf "%Y-%d-%m" "$B" +%s` - `date -jf "%Y-%d-%m" "$A" +%s`)/86400)), тобто загортання як форматів, так і змінних у подвійні лапки, інакше може не вдатися в іншому форматі дати (наприклад %b %d, %Y/ Jul 5, 2017)
Навіть якщо у вас немає дати GNU, ви, ймовірно, встановите Perl:
use Time::Local;
sub to_epoch {
my ($t) = @_;
my ($y, $d, $m) = ($t =~ /(\d{4})-(\d{2})-(\d{2})/);
return timelocal(0, 0, 0, $d+0, $m-1, $y-1900);
}
sub diff_days {
my ($t1, $t2) = @_;
return (abs(to_epoch($t2) - to_epoch($t1))) / 86400;
}
print diff_days("2002-20-10", "2003-22-11"), "\n";
Це повертається 398.041666666667- 398 днів та одна година завдяки переходу на літній час.
Питання з’явилося на моїй стрічці. Ось більш стислий метод із використанням модуля Perl
days=$(perl -MDateTime -le '
sub parse_date {
@f = split /-/, shift;
return DateTime->new(year=>$f[0], month=>$f[2], day=>$f[1]);
}
print parse_date(shift)->delta_days(parse_date(shift))->in_units("days");
' $A $B)
echo $days # => 398
Використання команди mysql
$ echo "select datediff('2013-06-20 18:12:54+08:00', '2013-05-30 18:12:54+08:00');" | mysql -N
Результат: 21
ПРИМІТКА. Для розрахунку використовуються лише ті частини дати, що мають значення
Посилання: http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_datediff
Ось мій робочий підхід із використанням zsh. Перевірено на OSX:
# Calculation dates
## A random old date
START_DATE="2015-11-15"
## Today's date
TODAY=$(date +%Y-%m-%d)
# Import zsh date mod
zmodload zsh/datetime
# Calculate number of days
DIFF=$(( ( $(strftime -r %Y-%m-%d $TODAY) - $(strftime -r %Y-%m-%d $START_DATE) ) / 86400 ))
echo "Your value: " $DIFF
Результат:
Your value: 1577
В основному, ми використовуємо функцію strftimereverse ( -r), щоб перетворити наш рядок дати назад у позначку часу, після чого ми робимо наш розрахунок.
Я б запропонував ще одне можливе рішення в Ruby. Схоже, це найменший і найчистіший на сьогоднішній день:
A=2003-12-11
B=2002-10-10
DIFF=$(ruby -rdate -e "puts Date.parse('$A') - Date.parse('$B')")
echo $DIFF
dateабо якусь мову сценаріїв), і я, чесно кажучи, вважаю, що Ruby - це хороший спосіб піти сюди. Це рішення дуже коротке і не використовує нестандартних бібліотек та інших залежностей. Насправді, я думаю, що шанси встановити Ruby вищі, ніж у GNU.
Використовуйте функції оболонки з http://cfajohnson.com/shell/ssr/ssr-scripts.tar.gz ; вони працюють в будь-якій стандартній оболонці Unix.
date1=2012-09-22
date2=2013-01-31
. date-funcs-sh
_date2julian "$date1"
jd1=$_DATE2JULIAN
_date2julian "$date2"
echo $(( _DATE2JULIAN - jd1 ))
Дивіться документацію за адресою http://cfajohnson.com/shell/ssr/08-The-Dating-Game.shtml
на unix вам слід встановити дати GNU. вам не потрібно відхилятися від bash. ось натягнуте рішення з урахуванням днів, щоб лише показати кроки. його можна спростити та продовжити до повних дат.
DATE=$(echo `date`)
DATENOW=$(echo `date -d "$DATE" +%j`)
DATECOMING=$(echo `date -d "20131220" +%j`)
THEDAY=$(echo `expr $DATECOMING - $DATENOW`)
echo $THEDAY
Це передбачає, що місяць становить 1/12 року:
#!/usr/bin/awk -f
function mktm(datespec) {
split(datespec, q, "-")
return q[1] * 365.25 + q[3] * 365.25 / 12 + q[2]
}
BEGIN {
printf "%d\n", mktm(ARGV[2]) - mktm(ARGV[1])
}
Спробуйте:
perl -e 'use Date::Calc qw(Delta_Days); printf "%d\n", Delta_Days(2002,10,20,2003,11,22);'
Припустимо, ми вручну синхронізуємо резервні копії Oracle DB на третинний диск. Потім ми хочемо видалити старі резервні копії на цьому диску. Отже, ось невеликий скрипт bash:
#!/bin/sh
for backup_dir in {'/backup/cmsprd/local/backupset','/backup/cmsprd/local/autobackup','/backup/cfprd/backupset','/backup/cfprd/autobackup'}
do
for f in `find $backup_dir -type d -regex '.*_.*_.*' -printf "%f\n"`
do
f2=`echo $f | sed -e 's/_//g'`
days=$(((`date "+%s"` - `date -d "${f2}" "+%s"`)/86400))
if [ $days -gt 30 ]; then
rm -rf $backup_dir/$f
fi
done
done
Змініть залишки та термін зберігання ("30 днів") відповідно до ваших потреб.
Для MacOS sierra (можливо, з Mac OS X yosemate),
Щоб отримати час епохи (секунди з 1970 р.) Із файлу та зберегти його у змінному:
old_dt=`date -j -r YOUR_FILE "+%s"`
Отримати час епохи поточного часу
new_dt=`date -j "+%s"`
Для обчислення різниці вище двох епох часу
(( diff = new_dt - old_dt ))
Щоб перевірити, чи різниця більше 23 днів
(( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days
echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s)) )) SECOUND
використовуйте його, щоб отримати вашу дату сьогодні і вашу секунду з дати, яку ви хочете. якщо ви хочете це з днями, просто розділіть його на 86400
echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s))/ 86400)) SECOUND