一.SHELL常用的日期函数
1.时间部分
% : 打印出%
%n : 下一行
%t : 跳格
%H : 小时(00..23)
%I : 小时(01..12)
%k : 小时(0..23)
%l : 小时(1..12)
%M : 分钟(00..59)
%p : 显示本地 AM 或 PM
%r : 直接显示时间 (12 小时制,格式为 hh:mm:ss [AP]M)
%s : 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数 %S : 秒(00..61)
%T : 直接显示时间 (24 小时制)
%X : 相当于 %H:%M:%S
%Z : 显示时区
2.日期部分
%a : 星期几 (Sun..Sat)
%A : 星期几 (Sunday..Saturday)
%b : 月份 (Jan..Dec)
%B : 月份 (January..December)
%c : 直接显示日期和时间
%d : 日 (01..31)
%D : 直接显示日期 (mm/dd/yy)
%F : 日期格式%Y-%m-%d
%h : 同 %b
%j : 一年中的第几天 (001..366)
%m : 月份 (01..12)
%U : 一年中的第几周 (00..53) (以 Sunday 为一周的第一天的情形)
%w : 一周中的第几天 (0..6)
%W : 一年中的第几周 (00..53) (以 Monday 为一周的第一天的情形)
%x : 直接显示日期 (mm/dd/yy)
%y : 年份的最后两位数字 (00.99)
%Y : 完整年份 (0000..9999)
3.使用命令
3.1.格式
date [OPTION][+FORMAT]
3.2.举个栗子
获取今天日期:
date "+%Y-%m %s"
date "+%F"
date "+%F %X"
date "+%F %T"
3.3.特别注意
Mac下的date命令是BSD(Berkeley Software Distribution)系的,Linux下date命令是GNU(GNU’s Not Unix)系,二者用法有一些区别.
BSD并不特指任何一个BSD衍生版本,而是类UNIX操作系统中的一个分支的总称.
Mac OS X和iOS实际上基于Darwin,Darwin是BSD其中一个分支.
获取前一天和获取后一天的写法不同:
- Mac,通过
-v
参数,-v-1d
代表前一天,-v-1y
代表上一年 - Linux,通过
--date
/-d
参数实现,--date='-1 day'
/-d '-1 day'
代表前一天,--date='-1 year'
代表上一年
# macos
date -v-1d +%F
# linux
date -d "-1 day" "+%F"
4.常用指令
一般服务器都是linux内核,macos不同的地方这里省略.
4.1.next/last
date -d 'next monday' +%Y%m%d # 下周一的日期
date -d 'next-day' +%Y%m%d # 明天的日期 或者:date -d tomorrow +%Y%m%d
date -d 'last-day' +%Y%m%d # 昨天的日期 或者:date -d yesterday +%Y%m%d
date -d 'last-month' +%Y%m # 上个月是几月
date -d 'next-month' +%Y%m # 下个月是几月
4.2.ago(seconds/hours/days/weeks/months/years)
date -d '30 days ago' # 30天前的日期
date -d 'dec 14 -2 weeks' # 相对:dec 14这个日期的两周前的日期
date -d '-100 days' # 100天以前的日期
date -d '50 days' # 50天后的日期
二.数仓中常用的自定义日期函数
1.自定义函数(DateUtils.sh)
#!/bin/sh
# Copyright (c) 2018 codingstandards. All rights reserved.
# file: DateUtils.sh
# description: Bash中关于日期的常用自定义函数
# license: LGPL
# author: darebeat
# email: darebeat@126.com
# version: 1.0
# date: 2018.08.28
#判断是否闰年
#input:year
#output: "true" "fase"
is_leap() {
Y=`expr substr $1 1 4`
r1=`expr $Y % 4`
r2=`expr $Y % 100`
r3=`expr $Y % 400`
if [ $r1 -eq 0 -a $r2 -ne 0 -o $r3 -eq 0 ]; then
FRUN="true"
else
FRUN="false"
fi
echo $FRUN
}
# 日期前一天,默认是当前日期
# 比如今天是2018年8月28日,那么结果就是2018-08-27
# usage:
# yesterday 20180828 %Y-%m-%d
# yesterday 20180828
yesterday() {
date -d "$1 1 day ago" "+${2:-%Y%m%d}"
}
# 日期所在的日期
curr_day() {
date -d "$1" "+${2:-%Y%m%d}"
}
# 日期所在周的第一天的日期
# usage:
# curr_week_first_day 20180828 %Y-%m-%d
# curr_week_first_day 20180828
curr_week_first_day() {
tmp_wd=$(date -d "$1" "+%w")
if [[ $tmp_wd == '0' ]]; then
tmp_wd='7'
fi
date -d "$(date -d "$1 -$tmp_wd day" "+${2:-%Y%m%d}") 1 day" "+${2:-%Y%m%d}"
}
# 日期环比上周的日期
# usage:
# wow_week_day 20180828 %Y-%m-%d
# wow_week_day 20180828
wow_week_day() {
date -d "$1 1 week ago" "+${2:-%Y%m%d}"
}
# 日期环比所在周的第一天的日期
# usage:
# wow_week_first_day 20180828 %Y-%m-%d
# wow_week_first_day 20180828
wow_week_first_day() {
curr_week_first_day $(wow_week_day $1) ${2:-%Y%m%d}
}
# 日期所在月的第一天的日期
# usage:
# curr_month_first_day 20180828 %Y-%m-01
# curr_month_first_day 20180828
curr_month_first_day() {
date -d "$1" "+${2:-%Y%m01}"
}
# 日期所在月的最后一天的日期
# usage:
# curr_month_last_day 20180828 %Y-%m-%d
# curr_month_last_day 20180828
curr_month_last_day() {
yesterday $(date -d "$1 1 month" "+%Y%m01") ${2:-%Y%m%d}
}
# 日期环比月第一天所在的日期
# usage:
# mom_month_first_day 20180828 %Y-%m-01
# mom_month_first_day 20180828
mom_month_first_day() {
date -d "$1 -1 month" "+${2:-%Y%m01}"
}
# 日期环比月所在的日期
# usage:
# mom_month_day 20180828 %Y-%m-%d
# mom_month_day 20180828
mom_month_day() {
tmp_lm_last_day=$(date -d "$(curr_month_last_day $(mom_month_first_day $1))" "+%e")
tmp_curr_last_day=$(date -d "$(curr_month_last_day $1)" "+%e")
tmp_curr_day=$(date -d "$1" "+%e")
if [[ ${tmp_lm_last_day} -lt ${tmp_curr_last_day} && ${tmp_curr_day} -ge ${tmp_lm_last_day} ]]; then
curr_month_last_day $(mom_month_first_day $1)
elif [[ ${tmp_lm_last_day} -ge ${tmp_curr_last_day} && ${tmp_curr_day} -ge ${tmp_curr_last_day} ]]; then
curr_month_last_day $(mom_month_first_day $1)
else
date -d "$1 -1 month" "+${2:-%Y%m%d}"
fi
}
# 日期同比月所在的日期
# usage:
# mym_month_day 20180828 %Y-%m-%d
# mym_month_day 20180828
mym_month_day() {
date -d "$1 -1 year" "+${2:-%Y%m%d}"
}
# 日期同比月第一天所在的日期
# usage:
# mym_month_first_day 20180828 %Y-%m-01
# mym_month_first_day 20180828
mym_month_first_day() {
date -d "$1 -1 year" "+${2:-%Y%m01}"
}
2.测试和使用案例
#!/usr/bin/env bash
declare -r CURR_DIR=$(cd `dirname $0`; pwd)
source ${CURR_DIR}/DateUtils.sh
test_date=20180328
echo $test_date
echo "获取日期的前一天的日期"
yesterday $test_date %Y-%m-%d
yesterday $test_date
echo "日期所在月的第一天的日期"
curr_month_first_day $test_date %Y-%m-01
curr_month_first_day $test_date
echo "日期环比上周的日期"
wow_week_day $test_date %Y-%m-%d
wow_week_day $test_date
echo "日期所在周的第一天的日期"
curr_week_first_day $test_date %Y-%m-%d
curr_week_first_day $test_date
echo "日期环比所在周的第一天的日期"
wow_week_first_day $test_date %Y-%m-%d
wow_week_first_day $test_date
echo "日期所在月的最后一天的日期"
curr_month_last_day $test_date %Y-%m-%d
curr_month_last_day $test_date
echo "日期环比月所在的日期"
mom_month_day $test_date %Y-%m-%d
mom_month_day $test_date
echo "日期环比月第一天所在的日期"
mom_month_first_day $test_date %Y-%m-01
mom_month_first_day $test_date
echo "日期同比月所在的日期"
mym_month_day $test_date %Y-%m-%d
mym_month_day $test_date
echo "日期同比月第一天所在的日期"
mym_month_first_day $test_date %Y-%m-01
mym_month_first_day $test_date