格式化纪元时间

时间:2014-02-10 20:36:22

标签: solaris ksh

我有这个命令,我发现here

/usr/bin/truss /usr/bin/date 2>&1 | 
    nawk -F= '/^time\(\)/ {gsub(/" "/,"",$2);printf "0t%d=Y\n", $2-30*86400}' |
    adb

打印2014 Jan 11 09:48:54。有谁知道如何将输出重新格式化为YYYYMMDDHH?

我必须在Solaris上使用ksh。我不能使用perl。

3 个答案:

答案 0 :(得分:0)

几条评论:

  • 第一个命令:

    /usr/bin/truss /usr/bin/date 2>&1 |
    nawk -F= '/^time\(\)/ {gsub(/" "/,"",$2);printf "0t%d=Y\n", $2-30*86400}'
    

可能会被更轻松,更简单的

取代
   nawk 'BEGIN {printf("0t%d=Y\n",srand()-30*86400)}'`
  • 我不确定adb是否理解0txx=Y语法,mdb肯定是这样。

那就是说,这里应该符合你的需要:

nawk 'BEGIN {printf("0t%d=Y\n",srand()-30*86400)}' | mdb | nawk '
function m2m(m)
{
    if(m=="Jan")return 1
    if(m=="Feb")return 2
    if(m=="Mar")return 3
    if(m=="Apr")return 4
    if(m=="May")return 5
    if(m=="Jun")return 6
    if(m=="Jul")return 7
    if(m=="Aug")return 8
    if(m=="Sep")return 9
    if(m=="Oct")return 10
    if(m=="Nov")return 11
    if(m=="Dec")return 12
}
{
    y=$1
    m=$2
    d=$3
    split($4,t,":")
    h=t[1]
    min=t[2]
    printf("%s%02d%02d%02d%02d\n",y,m2m(m),d,h,min)
}'

注意:

  • srand(不要与rand混淆)在调用时返回上一个种子。
  • 当没有传递任何参数时,srand使用“当天时间”作为种子。
  • srand内部初始化nawk时,第一个srand()调用会返回当天的时间,即自纪元以来经过的秒数。
  • 如果您想要一种严格的可移植方式,则需要在获取其返回值之前运行第一个srand()调用,但在Solaris下不需要这样做。
  • 与使用truss不同,这是便携式的(即POSIX)。

答案 1 :(得分:0)

编辑:最初我已经形成了一个在Linux上运行良好的响应,但在Solaris上却没有。现在这个时间要长得多,原来的答案如下。

要在Solaris上完全执行此操作,只能使用date函数。的种类。您还必须创建一些shell函数来帮助减去给定日期之后的天数。

使用以下功能,您可以执行以下操作以获得所需的结果:

$ mydate="$(date '+%Y%m%d')"
$ hours="$(date '+%H')"
$ echo "$(date_subtract "${mydate}" 30)${hours}" | adb

或类似的......

在Solaris上,date命令仅提供公历日期。对于这个问题,这很难处理,所以我创建了一个shell函数gregorian_to_julian,它可以将'YYYYMMDD'格式的日期转换为'YYYYDDD'的Julian日期。

function gregorian_to_julian {
    # "Expecting input as YYYYMMDD."
    typeset gregorian_date=$1
    typeset _year=$(echo "${gregorian_date}" | cut -c1-4)
    typeset _month=$(echo "${gregorian_date}" | cut -c5-6)
    typeset _day=$(echo "${gregorian_date}" | cut -c7-8)

    typeset days
    days[01]=31
    days[02]=$(( days[01] + 28 ))
    if (( _year % 4 == 0 )) && (( _year % 100 != 0 )) || (( _year % 400 == 0 )); then
        days[02]=$(( days[01] + 29 ))
    fi
    days[03]=$(( 31 + days[02] ))
    days[04]=$(( 30 + days[03] ))
    days[05]=$(( 31 + days[04] ))
    days[06]=$(( 30 + days[05] ))
    days[07]=$(( 31 + days[06] ))
    days[08]=$(( 31 + days[07] ))
    days[09]=$(( 30 + days[08] ))
    days[10]=$(( 31 + days[09] ))
    days[11]=$(( 30 + days[10] ))

    typeset julian_date=0
    case "${_month}" in
        "01") julian_date=$_day ;;
        "02") julian_date=$(( days[01] + _day )) ;;
        "03") julian_date=$(( days[02] + _day )) ;;
        "04") julian_date=$(( days[03] + _day )) ;;
        "05") julian_date=$(( days[04] + _day )) ;;
        "06") julian_date=$(( days[05] + _day )) ;;
        "07") julian_date=$(( days[06] + _day )) ;;
        "08") julian_date=$(( days[07] + _day )) ;;
        "09") julian_date=$(( days[08] + _day )) ;;
        "10") julian_date=$(( days[09] + _day )) ;;
        "11") julian_date=$(( days[10] + _day )) ;;
        "12") julian_date=$(( days[11] + _day )) ;;
    esac
    julian_date="${_year}${julian_date}"
    echo "${julian_date}"
}

了解OP希望将日期格式化为格里高利日期,我创建了第二个函数julian_to_gregorian,它将Julian日期转换回来。

function julian_to_gregorian {
    # "Expecting input as YYYYDDD."
    #set -x
    typeset julian_date=$1

    typeset _year="$(echo "${julian_date}" | cut -c1-4)"
    typeset _month=""
    typeset julian_day="$(echo "${julian_date}" | cut -c5-7)"
    typeset -RZ2 _day=0
    typeset days
    days[01]=31
    days[02]=$(( days[01] + 28 ))
    if (( _year % 4 == 0 )) && (( _year % 100 != 0 )) || (( _year % 400 == 0 )); then
        days[02]=$(( days[01] + 29 ))
    fi
    days[03]=$(( 31 + days[02] ))
    days[04]=$(( 30 + days[03] ))
    days[05]=$(( 31 + days[04] ))
    days[06]=$(( 30 + days[05] ))
    days[07]=$(( 31 + days[06] ))
    days[08]=$(( 31 + days[07] ))
    days[09]=$(( 30 + days[08] ))
    days[10]=$(( 31 + days[09] ))
    days[11]=$(( 30 + days[10] ))

    if (( days[11] < julian_day )); then    _month="12"; _day=$(( julian_day - days[11] ));
    elif (( days[10] < julian_day )); then  _month="11"; _day=$(( julian_day - days[10] ));
    elif (( days[09] < julian_day )); then  _month="10"; _day=$(( julian_day - days[09] ));
    elif (( days[08] < julian_day )); then  _month="09"; _day=$(( julian_day - days[08] ));
    elif (( days[07] < julian_day )); then  _month="08"; _day=$(( julian_day - days[07] ));
    elif (( days[06] < julian_day )); then  _month="07"; _day=$(( julian_day - days[06] ));
    elif (( days[05] < julian_day )); then  _month="06"; _day=$(( julian_day - days[05] ));
    elif (( days[04] < julian_day )); then  _month="05"; _day=$(( julian_day - days[04] ));
    elif (( days[03] < julian_day )); then  _month="04"; _day=$(( julian_day - days[03] ));
    elif (( days[02] < julian_day )); then  _month="03"; _day=$(( julian_day - days[02] ));
    elif (( days[01] < julian_day )); then  _month="02"; _day=$(( julian_day - days[01] ));
    else
        _month="01"; _day=${julian_day};
    fi
    echo "${_year}${_month}${_day}"
}

第三个函数date_subtract采用格里高利日期,将其转换为朱利安,进行日期数学运算,并转换回格里高利。

function date_subtract {
    typeset julian_from_date=$(gregorian_to_julian "$1")
    typeset number_of_days=$2
    typeset julian_year=$(echo "${julian_from_date}" | cut -c1-4)
    typeset julian_days=$(echo "${julian_from_date}" | cut -c5-7)
    typeset leap_year="FALSE"
    if (( julian_days - number_of_days > 0 )); then
        (( julian_days -= number_of_days ))
    else
        (( julian_year -= 1 ))

        if (( julian_year % 4 == 0 )) && (( julian_year % 100 != 0 )) || (( julian_year % 400 == 0 )); then
            leap_year="TRUE"
        fi
        if [[ "${leap_year}" == "TRUE" ]]; then
            (( julian_days = julian_days + 366 - number_of_days ))
        else
            (( julian_days = julian_days + 365 - number_of_days ))
        fi
    fi
    typeset gregorian_date=$(julian_to_gregorian "${julian_year}${julian_days}")
    echo "${gregorian_date}"
}

编辑:以下适用于Linux。而且更简单。

如果您需要格式为YYMMDDHH的日期,那么这很简单,就像@FrankH一样。在他的评论中指出:

date +"%Y%m%d%H"

更棘手的部分是计算30天前的日期,这似乎是你的意图。 date命令可以占用纪元以来的秒数并将其转换为日期字符串。这是通过-d标志完成的。 e.g。

$ date -d @123456789
Thu Nov 29 15:33:09 CST 1973

所以,如果你需要三十天前的日期,我们可以采取这个原则,并做一些数学计算,以获得所需的价值。

请注意date '+%s'给出了自纪元以来的秒数。

$ date -d @$(( $(date '+%s') - $((60 * 60 * 24 * 30 )) )) '+%Y%m%d%H'
2014011211

如果您需要将该日期字符串传递给adb,那么您可以使用$(...)包围该命令。

echo $( date -d @$(( $(date '+%s') - $((60 * 60 * 24 * 30 )) )) '+%Y%m%d%H' ) | adb

答案 2 :(得分:0)

如果您有Solaris 11,答案很简单,因为kshksh93Solaris 11 ksh man page包含有关printf的信息:

A %(date-format)T format can be use to treat an argument as a date/time string
and to format the date/time according to the date-format as defined for the
date(1) command.

ksh手册页中未指定允许的日期/时间字符串格式,但在AST tm(3) man page中(有些)提及。种类繁多。特别是,这将做你想要的:

$ printf "%(%Y%m%d%H)T\n" 
2014021118
$ printf "%(%Y%m%d%H)T\n" now
2014021118
$ printf "%(%Y%m%d%H)T\n" "30 days ago"
2014011218