在#!/ bin / bash中。Unix命令获取一个月中第一个工作日的日期


8

我正在寻找一个直接的Unix命令来获取下个月的第一个星期日,下个月的第一个星期一,下个月的第一个星期二,下个月的第一个星期三等。

  1. 我需要完整的日期格式(时间不是必需的)

  2. 我可以获得2、3、4等数字。由于我只想要数字,所以我需要日期格式(包括日,月,年)

    $ NEXT_MONTH=`date +'%m %Y' -d 'next month'`
    $ echo $NEXT_MONTH
    04 2017
    
    $ NEXT_SUNDAY=`cal $NEXT_MONTH | awk 'NF==7 && !/^Su/{print $1;exit}'`
    $ echo $NEXT_SUNDAY
    2
  3. 我需要这些日期来发送电子邮件组的通知。

例如:我可以得到下个月的第一个星期六,如下所示。

$ firstofmonth=$(date -d '+1 months' '+%Y%m01')
20170401

$ firstsaturday=$(date -d "$firstofmonth" '+%Y-%m')-$((7 - \
                $(date -d "$firstofmonth" '+%u')     ))    
2017-04-1

Answers:


11

ksh93

$ printf '%(%F)T\n' 'next month, first Monday'
2017-04-03

bash,因为4.2现在%(<format)T在其printfbuitin中支持a ,但不支持解析这种日期表达式的功能。

如果您必须使用bash并且想要使用它%(<format>)T,您仍然可以在不进行分叉的情况下进行操作:

printf -v code '%(
  t=$((%s + (12 - %-H) * 60 * 60))
  increment=$((8 - %u))
  current_month=%m)T' -1
eval "$code"
until
  t=$((t + increment * 24 * 60 * 60)) # next Monday around mid-day
  printf -v code '%(date=%F month=%m)T' "$t"
  eval "$code"
  [ "$month" != "$current_month" ] # until be get to next month
do
  increment=7 # the first increment is the number of days
              # til Monday. Next increments are just a week.
done
echo "$date"

#!/ bin / bash。我在bash中收到以下错误$ printf'%(%F)T \ n''下个月,第一个星期一'-bash:printf:`(':无效的格式字符
Hima

1
@Hima,我确实在ksh93中说过bash是ksh的未完成克隆(具有(t)csh和zsh的某些功能,甚至有一些自己的功能)。的最新版本bash增加了对printf '%(format)T'from的支持ksh93,但无法解析这种日期规范。用替换您的爆炸#! /path/to/ksh93 -
斯特凡Chazelas

bash是ksh的未完成克隆” –我一直都这样。
蒂姆·肯尼迪

@Stephene,我尝试使用以下命令获取上周六的下个月$ cal 04 2017 | awk'NF <= 7 {print $ 6}'| grep -v“ ^ $” | tail -1 28它显示数字28,但是我正在寻找完整的日期04/28/2017,请建议。
Hima

9

假设使用GNU date(为此-d您正在使用自己),并且有一个类似zsh的shell用于{1..7}

$ for i in {1..7} ; do \
    LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
  done | awk '/Mon/ {print $1}'
2017-04-03

将替换awk Mon为所需的任何工作日(用于LC_ALL=C获取英文月份名称,而不考虑用户的语言环境)。另外,如果要在一周的每一天重新查询,最好将其存储到变量中:

$ days=$(for i in {1..7} ; do \
           LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
         done)

$ for i in Mon Tue Wed Thu Fri Sat Sun ; do \
    echo "${days}" | awk "/${i}/"'{print $1}' ; \
  done
2017-04-03
2017-04-04
2017-04-05
2017-04-06
2017-04-07
2017-04-01
2017-04-02

同样在bash中,此代码返回下个月的第一个星期日,星期一,星期三,因此,星期五,星期六。谢谢。我认为,我可以修改此命令以获取下个月的上个星期日,星期一,星期三等。让我尝试一下。
Hima

嗨,我尝试使用以下命令在上周六获取下个月$ cal 04 2017 | awk'NF <= 7 {print $ 6}'| grep -v“ ^ $” | tail -1它显示数字28,但我正在寻找完整的日期,如04/28/2017,请建议。
Hima

“对于{1..7}中的i;在日期'+%Y-%m-%d%a'-d“ $(date +%Y%m01 -d'2 months')$ {i}天之前“;完成| awk'/ Sat / {print $ 1}'”-这将给出2017-04-29,这是下个月的最后一个星期六。此代码向前2个月进行到该月的第一天,然后向后1-7天返回以获得上个月的最后7天的数据。我个人会避免使用cal,因为我在这里尝试了其他示例,而在我的版本(CentOS 6)上根本没有任何效果。
parkamark

2

如果系统上可用,PHP实际上使使用文本输入解析日期非常容易。

例:

bash-[522]$ php -qr 'date_default_timezone_set("UTC"); echo date("d-m-Y\n", strtotime("first monday of next month"));'
03-04-2017

我的.bashrc中有此功能:

get_date ()
{
    text="$*";
    php -qr "date_default_timezone_set(\"UTC\"); echo date(\"d-m-Y\n\", strtotime(\"$text\"));"
}

我可以用作:

bash-[523]$ get_date first monday of next month
03-04-2017

编辑添加选项以使用cal

几乎每个拥有的系统都bash将拥有cal。日历程序。您可以通过运行的组合获得日期为第一每周一天的清单caldateawk,如下所示:

 cal -hN $(date -d 'next month' +%b' '%Y) | grep -v $(date -d 'next month' +%b) | awk -v date=$(date -d 'next month' +%Y-%m-) '{ printf "%s: "date"%02i\n", $1, $2; }'

这将为您提供以下输出:

Su: 2017-04-02
Mo: 2017-04-03
Tu: 2017-04-04
We: 2017-04-05
Th: 2017-04-06
Fr: 2017-04-07
Sa: 2017-04-01

在awk语句中更改$2$NF,以获取一个月中每一天的最后一次出现的日期。


它不能在bash中工作,$ php -qr'date_default_timezone_set(“ UTC”); echo date(“ dmY \ n”,strtotime(“下个月的第一个星期一”));' -bash:php:找不到命令。请让我知道以bash方式完成它的方法。而且,该命令将在下个月的星期日至周六通过Sun获得。我确实尝试过,但它是如何引发错误的。谢谢 ..!!
Hima

意味着您尚未php安装。我曾与一个使用的例子更新caldateawk命令。
蒂姆·肯尼迪

我尝试了此命令并引发错误。谢谢。!!$ cal -hN $(date -d'next month'+%b''%Y)| grep -v $(date -d'next month'+%b)| awk -v date = $(date -d'next month'+%Y-%m-)'{printf“%s:” date“%02i \ n”,$ 1,$ 2; }'cal:无效选项-h用法:cal [-13smjyV] [[month] year]
Hima
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.