#!/bin/sh



set -u
umask 0022
export LC_ALL=C
export PATH="$(command -p getconf PATH 2>/dev/null)${PATH+:}${PATH-}"
case $PATH in :*) PATH=${PATH#?} ;; esac
export UNIX_STD=2003 # to make HP-UX conform to POSIX

print_usage_and_exit() {
	cat <<-USAGE 1>&2
		USAGE   : ${0##*/} [datetime_text_or_file]    # Cal.-time -> Unixtime
		          ${0##*/} -r [unixtime_text_or_file] # Unixtime -> Cal.-time
		Args    : datetime_text_or_file ... A time to converting
		Options : -r ...................... Swithes mode to Unixtime -> Cal.-time
		Version : 2020-05-06 22:42:19 JST
		          (POSIX Bourne Shell/POSIX commands)
	USAGE
	exit 1
}


case "${1:-}" in --version | --help | -h) print_usage_and_exit ;; esac


exec awk '
BEGIN {
  unixtime2YYYYMMDDhhmmss_init("LOCALTIME"); # initialize with localtime mode
  revmode   = 0;
  fromstdin = 1;

  for (i=1; i<ARGC; i++) {
    if (ARGV[i] == "-r") {
      revmode = 1;
      continue;
    }
    fromstdin = 0;
    if ((ARGV[i] == "-") && (i == ARGC-1))                   {
      fromstdin = 1;
      break;
    } else if ((revmode == 0) && match(ARGV[i], /^[0-9]+$/)) {
      printf("%d\n",YYYYMMDDhhmmss2unixtime(ARGV[i]));
    } else if (revmode == 0) {
      while (getline < ARGV[i]) {
        printf("%d\n",YYYYMMDDhhmmss2unixtime($1));
      }
    } else if ((revmode >  0) && match(ARGV[i], /^-?[0-9]+$/)) {
      print unixtime2YYYYMMDDhhmmss(ARGV[i]);
    } else {
      while (getline < ARGV[i])                              {
        print unixtime2YYYYMMDDhhmmss($1);
      }
    }
  }

  if ((fromstdin > 0) && (revmode == 0)) {
    while ("cat" | getline) {
      printf("%d\n",YYYYMMDDhhmmss2unixtime($1));
    }
  } else if (fromstdin > 0)              {
    while ("cat" | getline) {
      print unixtime2YYYYMMDDhhmmss($1);
    }
  }
}

function unixtime2YYYYMMDDhhmmss_init(localtime_flag, gm,lo) {
  max_calced_year = 1970;              # To remember every days on 01/01 from
  days_on_Jan1st_from_epoch[1970] = 0; # the Epoch which was calculated once

  split("31 0 31 30 31 30 31 31 30 31 30 31", days_of_month);

  if (localtime_flag == "LOCALTIME") {
    gm      = YYYYMMDDhhmmss2unixtime("'$(TZ=UTC+0 date '+%Y%m%d%H%M%S')'");
    lo      = YYYYMMDDhhmmss2unixtime("'$(date '+%Y%m%d%H%M%S')'");
    offset  = lo - gm;
    offset -= (offset%2); # calcell the time lag of the two date starting time
  } else {
    offset  = 0;
  }
}

function unixtime2YYYYMMDDhhmmss(ut, Y,M,D,h,m,s,t,i,j) {
  ut += offset;
  if (ut < 0) {return -1;}

  s = ut % 60;  t = int(ut/60);
  m =  t % 60;  t = int( t/60);
  h =  t % 24;
  days_from_epoch = int( t/24);

  Y = int(days_from_epoch/365.2425)+1970+1;
  if (Y > max_calced_year) {
     i = days_on_Jan1st_from_epoch[max_calced_year];
     for (j=max_calced_year; j<Y; j++) {
       i += (j%4!=0)?365:(j%100!=0)?366:(j%400!=0)?365:366;
       days_on_Jan1st_from_epoch[j+1] = i;
     }
     max_calced_year = Y;
  }
  for (;;Y--) {
    if (days_from_epoch >= days_on_Jan1st_from_epoch[Y]) {
      break;
    }
  }

  days_of_month[2] = (Y%4!=0)?28:(Y%100!=0)?29:(Y%400!=0)?28:29;
  D = days_from_epoch - days_on_Jan1st_from_epoch[Y] + 1;
  for (M=1; ; M++) {
    if (D > days_of_month[M]) {
      D -= days_of_month[M];
    } else {
      break;
    }
  }

  return sprintf("%04d%02d%02d%02d%02d%02d",Y,M,D,h,m,s);
}

function YYYYMMDDhhmmss2unixtime(YYYYMMDDhhmmss, Y,M,D,h,m,s,l) {
  l = length(YYYYMMDDhhmmss);
  if        (l <  5) { # invalid
    return -1;
  } else if (l <  8) { # YYMMMDD only
    Y = substr(YYYYMMDDhhmmss,  1,l-4)*1+int('$(date '+%Y')'/100)*100;
    M = substr(YYYYMMDDhhmmss,l-3,  2)*1;
    D = substr(YYYYMMDDhhmmss,l-1,  2)*1;
    h = 0; m = 0; s = 0;
  } else if (l < 12) { # YYYYMMDD only
    Y = substr(YYYYMMDDhhmmss,  1,l-4)*1;
    M = substr(YYYYMMDDhhmmss,l-3,  2)*1;
    D = substr(YYYYMMDDhhmmss,l-1    )*1;
    h = 0; m = 0; s = 0;
  } else {             # YYYYMMDDhhmmss
    Y = substr(YYYYMMDDhhmmss,  1,l-10)*1;
    M = substr(YYYYMMDDhhmmss,l-9,   2)*1;
    D = substr(YYYYMMDDhhmmss,l-7,   2)*1;
    h = substr(YYYYMMDDhhmmss,l-5,   2)*1;
    m = substr(YYYYMMDDhhmmss,l-3,   2)*1;
    s = substr(YYYYMMDDhhmmss,l-1     )*1;
  }

  if ((s>60) || (m>59) || (h>23) || (M>12)) {return -1;}
  days_of_month[2] = (Y%4!=0)?28:(Y%100!=0)?29:(Y%400!=0)?28:29;
  if (D > days_of_month[M]                ) {return -1;}

  if (M<3) {M+=12; Y--;}

  return (365*Y+int(Y/4)-int(Y/100)+int(Y/400)+int(306*(M+1)/10)-428+D-719163)*86400+(h*3600)+(m*60)+s-offset;
}
' ${1+"$@"}
