static char sccsid[]="%Z% %M% %I% %E% %U%";
/********************************************/
/*											*/
/*	  coded by A.Kobayashi 2022.07.31		*/
/*											*/
/********************************************/
#include "akxcommon.h"

char *PC_SYS_DATE_FORMAT = "YYYY/MM/DD HH:MI:SS";
char *PC_DATE_TERM = "YMDHNS";

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : axConvDate                                                  */
/*  機能 : 年月日時分秒の文字列から年、月、日、時、分、秒を生成する    */
/*         年、月、日、時、分、秒は、それぞれの正しい範囲に修正される  */
/*         月のときは日にちをその月の日数で割った値の差が加わる        */
/*  引数 : IN  : ymd    : 年月日[△時分秒]の文字列                     */
/*                        以下の形式をサポートする                     */
/*                        ・年月日                                     */
/*                          [YY]YY{/|-|.}MM[{/|-|.}DD]                 */
/*                          [YY]YYMMDD                                 */
/*                          年が100未満のときは、>=50なら、2000年代    */
/*                                               < 50なら、1900年代    */
/*                        ・時分秒                                     */
/*                          H[H]:N[N][:S[S]] or HH[MM[SS]]             */
/*         OUT : ymda() : ymda(0) = 年                                 */
/*                        ymda(1) = 月                                 */
/*                        ymda(2) = 日                                 */
/*                        以下は、ymdaの配列が5以上のとき設定される    */
/*                        ymda(3) = 時                                 */
/*                        ymda(4) = 分                                 */
/*                        ymda(5) = 秒                                 */
/*                        ymdで年月日または時分秒がないときは、        */
/*                        それぞれの組で、全て、-1が設定される         */
/*               dlma() : dlma(0) = 年月日の1 番目の区切り             */
/*                        dlma(1) = 年月日の2 番目の区切り             */
/*                        以下は、dlmaの配列が2以上のとき設定される    */
/*                        dlma(2) = 時分秒の区切り                     */
/*  返却 : 処理結果 = 0 正常                                           */
/*                  = 0x01 年を修正した                                */
/*                  = 0x02 月を修正した                                */
/*                  = 0x04 日を修正した                                */
/*                  = 0x10 時を修正した                                */
/*                  = 0x20 分を修正した                                */
/*                  = 0x40 秒を修正した                                */
/*                  < ymd形式エラー                                    */
/*  作成 : 2016/12/26 Akito Kobayashi                                  */
/*  更新 : 2017/01/20 Akito Kobayashi Add Time                         */
/***********************************************************************/
int axConvDate(ymd,ymda,max_ymda,dlma,max_dlma)
char *ymd;
int ymda[],max_ymda;
char dlma[];
int max_dlma;
{
	ParList pa_dat;
	int ret,rc,yyyy,mm,dd,hh,nn,ss,pos1,pos2,size;
	char c1,c2,c3,dat[128],hns0[16],hns[16],ymd0[16];

	ret = akxtstrim2(0x04,ymd,strlen(ymd),&pa_dat,NULL);
	memzcpy(dat,pa_dat.par,ret);
	c1 = c2 = c3 = '\0';
	ret = yyyy = mm = dd = hh = nn = ss = 0;
	*hns0 = '\0';
	strcpy(ymd0,dat);
	if (*dat) {
		*hns = '\0';
		pos1 = instrchar(dat,' ');
		if (pos1 > 0) {
			strcpy(hns,dat+pos1);
			dat[pos1-1] = '\0';
			strcpy(ymd0,dat);
/*
printf("axConvDate: pos1=%d dat=[%s] hns=[%s]\n",pos1,dat,hns);
*/
		}
		pos1 = instrchars(dat,"/-.");
		if (pos1 == 1)
			ret = -1;
		else if (pos1 > 0) {
			c1 = *(dat+pos1-1);
			if (pos1 > 5)
				yyyy = 9999;
			else 
				yyyy = atoi2(dat,pos1-1);
/*
printf("axConvDate: pos1=%d yyyy=%d\n",pos1,yyyy);
*/
			if (yyyy < 100) {
				if (yyyy <= 50)
					yyyy = 2000 + yyyy;
				else
					yyyy = 1900 + yyyy;
			}
			strcpy(dat,dat+pos1);
			pos2 = instrchars(dat,"/-.");
/*
printf("axConvDate: pos2=%d dat=[%s]\n",pos2,dat);
*/
			if (pos2 == 1)
				ret = ret - 2;
			else if (pos2 > 0) {
				c2 = *(dat+pos2-1);
				mm = atoi2(dat,pos2-1);
				strcpy(dat,dat+pos2);
				if (!*dat)
					ret = ret - 4;
				else
					dd = atoi(dat);
			}
			else {
				mm = atoi(dat);
				dd = 0;
			}
/*
printf("axConvDate: mm=%d dd=%d\n",mm,dd);
*/
		}
		else if (instrchar(dat,':') > 0) {
			if (*hns)
				ret = -256;
			else {
				strcpy(hns,dat);
				*ymd0 = '\0';
			}
		}
		else {
			size = strlen(dat);
			if (size==8 || size==6) {
				if (size == 8) {
					yyyy = atoi2(dat,4);
					strcpy(dat,dat+4);
				}
				else {
					yyyy = atoi2(dat,2);
					if (yyyy <= 50)
						yyyy = 2000 + yyyy;
					else
						yyyy = 1900 + yyyy;
					strcpy(dat,dat+2);
				}
				mm = atoi2(dat,2);
				dd = atoi(dat+2);
			}
			else
				ret = -8;
		}
		strcpy(hns0,hns);
		if (max_ymda>=5 && *hns) {
			pos1 = instrchar(hns,':');
			if (pos1 > 0) {
				c3 = ':';
				if (pos1 < 2)
					ret = ret - 16;
				else {
					hh = atoi2(hns,pos1-1);
					strcpy(hns,hns+pos1);
					pos1 = instrchar(hns,':');
/*
printf("axConvDate: hh=%d pos1=%d hns=[%s]\n",hh,pos1,hns);
*/
					if (pos1 > 0) {
						if (pos1 < 2)
							ret = ret - 32;
						else {
							nn = atoi2(hns,pos1-1);
							strcpy(hns,hns+pos1);
							if (*hns)
								ret = ret - 128;
							else
								ss = atoi(hns);
						}
					}
					else {
						if (!*hns)
							ret = ret - 64;
						else
							nn = atoi(hns);
					}
				}
			}
			else {
				pos1 = strlen(hns);
				if (pos1 >= 6) ss = atoi2(hns+4,2);
				if (pos1 >= 4) nn = atoi2(hns+2,2);
				if (pos1 >= 2) hh = atoi2(hns,2);
			}
		}
	}
/*	if (!ret) {	*/
		if (max_ymda >= 6) {
			if (*hns0) {
				ret = axCheckTime(hh,nn,ss,ymda);
				ret = ret * 16;
				mem_cpy_int(ymda+3,ymda,3);
			}
			else
				mem_set_int(ymda+3,-1,3);
		}
		if (*ymd0)
			ret = axCheckDate(yyyy,mm,dd,ymda);
		else
			mem_set_int(ymda,-1,3);
/*	}	*/
	dlma[0] = c1;
	dlma[1] = c2;
	dlma[2] = '\0';
	if (max_dlma >= 3) {
		dlma[2] = c3;
		dlma[3] = '\0';
	}
	return ret;
}

int axAddToDate(ymda,max_ymda,term,add)
int ymda[],max_ymda;
char *term;
int add;
{
	static char dat[64];
	int hmsa[3],pos,ret,len;

	ret = 0;
	if (max_ymda >= 5)
		mem_cpy_int(hmsa,ymda+3,3);
	else
		mem_set_int(hmsa,0,3);
	pos = get_date_term_no(term);
	if (pos>=1 && pos<=6) {
		if (pos >= 4) {
			ret = axAddToTimeDay(hmsa,term,add);
			mem_cpy_int(ymda+3,hmsa,3);
/*
printf("axAddToDate: dlm=[%s]\n",dlm);
*/
			ret = axAddToDateSub(ymda,"D",ret);
		}
		else
			ret = axAddToDateSub(ymda,term,add);
	}
	return ret;
}

int axAddToDateSub(ymda,term,add)
int ymda[];
char *term;
int add;
{
	int yyyy,ret,i,last_dd,ymda2[3],term_no;
	long my,ld;

	mem_cpy_int(ymda2, ymda, 3);
	term_no = get_date_term_no(term);
	if (term_no>=1 && term_no<=3) {
		yyyy = ymda2[0];
		if (term_no == 1) {
			yyyy = yyyy + add;
			if (yyyy < 0) yyyy = 0;
			ymda2[0] = yyyy;
		}
		else {
			my = yyyy*12 + ymda2[1];
			if (term_no == 2) {
				my += add;
				ld = 1;
			}
			else if (term_no == 3) {
				ld = ymda2[2];
				ld += add;
				if (ld <= 0) {
					for (;;) {
						if (ld > 0) break;
						my--;
						ret = ConvYM_D(my,31,ymda2);
						ld += ymda2[2];
					}
				}
				else {
					for (;;) {
						ret = ConvYM_D(my,31,ymda2);
						last_dd = ymda2[2];
						if (ld <= last_dd) break;
						ld -= last_dd;
						my++;
					}
				}
			}
			ret = ConvYM_D(my,ld,ymda2);
		}
		for (i=0;i<3;i++) {
			if (i < term_no) ymda[i] = ymda2[i];
		}
	}
	return ret;
}

int axAddToTimeDay(hnsa,term,add)
int hnsa[];
char *term;
int add;
{
	int pos,i,t,tt;

	t = 0;
	pos = get_date_term_no(term);
	if (pos>=4 && pos<=6) {
		/* term未満はチェックしない */
		tt = 0;
		for (i=0;i<=2;i++) {
			tt = tt * 60;
			if (pos-4 >= i) tt = tt + hnsa[i];
		}

		/* add秒にして加える */
		t = add;
		for (i=2;i>=pos-3;i--) t = t * 60;
		tt = tt + t;

		/* 1日に収まるように修正する */
		t = 0;
		if (tt >= 0) {
			while (tt >= 86400) {
				t = t + 1;
				tt = tt - 86400;
			}
		}
		else {
			while (tt < 0) {
				t = t - 1;
				tt = tt + 86400;
			}
		}

		/* 時、分、秒に戻す */
		if (pos >= 6) hnsa[2] = tt % 60;
		tt /= 60;
		if (pos >= 5) hnsa[1] = tt % 60;
		if (pos >= 4) hnsa[0] = tt / 60;
	}
	return t;
}

int axSetDatePart(ymda,max_ymda,term,val)
int ymda[],max_ymda;
char *term;
int val;
{
	int pos,ret,hmsa[3];

	pos = get_date_term_no(term);
	if (pos >= 4) {
		if (max_ymda > 3) {
			mem_cpy_int(hmsa,ymda+3,3);
			ret = axSetTimePart(hmsa,term,val);
			mem_cpy_int(ymda+3,hmsa,3);
		}
	}
	else if (pos > 0) {
		ymda[pos - 1] = val;
		ret = axCheckDate(ymda[0],ymda[1],ymda[2],ymda);
	}
	return ret;
}

int axSetTimePart(hmsa,term,val)
int hmsa[];
char *term;
int val;
{
	int pos,ret;

	pos = get_date_term_no(term);
	if (pos >= 4) {
		hmsa[pos - 4] = val;
	}
	ret = axCheckTime(hmsa[0],hmsa[1],hmsa[2],hmsa);
}

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : axCheckDate                                                 */
/*  機能 : 年、月、日をそれぞれの正しい範囲に修正する                  */
/*  引数 : IN  : v_Year  : 年 <0 なら、0                               */
/*               v_Month : 月 <1 なら、1、 >12 なら、12                */
/*               v_Day   : 日 <1 なら、1                               */
/*                            >その月の最終日 なら、その月の最終日     */
/*         OUT : ymda() : ymda(0) = 年                                 */
/*                        ymda(1) = 月                                 */
/*                        ymda(2) = 日                                 */
/*  返却 : 処理結果 = 0 正常                                           */
/*                  = 0x01 年を修正した                                */
/*                  = 0x02 月を修正した                                */
/*                  = 0x04 日を修正した                                */
/*  作成 : 2016/12/26 Akito Kobayashi                                  */
/*  更新 : 2019/10/01 Akito Kobayashi Mod use get_day_num()            */
/***********************************************************************/
int axCheckDate(v_Year,v_Month,v_Day,ymda)
int v_Year,v_Month,v_Day,ymda[];
{
	int num,ret;

	ret = 0;
	/* 年の修正 */;
	if (v_Year < 0) {
		v_Year = 0;
		ret = 1;
	}

	ret = ret + 2;
	/* 月の修正 */;
	if (v_Month < 1)
		v_Month = 1;
	else if (v_Month > 12)
		v_Month = 12;
	else
		ret -= 2;

	ret = ret + 4;
	/* 日の修正 */;
	if (v_Day < 1)
		v_Day = 1;
	else {
		num = get_day_num(v_Year,v_Month,0);
		if (v_Day > num)
			v_Day = num;
		else
			ret -= 4;
	}

	ymda[0] = v_Year;
	ymda[1] = v_Month;
	ymda[2] = v_Day;

	return ret;
}

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : axCheckTime                                                 */
/*  機能 : 時、分、秒をそれぞれの正しい範囲に修正する                  */
/*  引数 : IN  : hh     : 時 <0,>23 なら、0,23                         */
/*               mi     : 分 <0,>23 なら、0,23                         */
/*               ss     : 秒 <0,>23 なら、0,23                         */
/*         OUT : hmsa() : hmsa(0) = 年                                 */
/*                        hmsa(1) = 月                                 */
/*                        hmsa(2) = 日                                 */
/*  返却 : 処理結果 = 0 正常                                           */
/*                  = 0x01 時を修正した                                */
/*                  = 0x02 分を修正した                                */
/*                  = 0x04 秒を修正した                                */
/*  作成 : 2016/12/27 Akito Kobayashi                                  */
/*  更新 :                                                             */
/***********************************************************************/
int axCheckTime(hh,mi,ss,hmsa)
int hh,mi,ss,hmsa[];
{
	int ret,i,m,n;

	hmsa[0] = hh;
	hmsa[1] = mi;
	hmsa[2] = ss;
	m = 23;
	n = 1;
	ret = 0;
	for (i=0;i<3;i++) {
		ret += n;
		if (hmsa[i] < 0)
			hmsa[i] = 0;
		else if (hmsa[i] > m)
			hmsa[i] = m;
		else
			ret -= n;
		n += n;
		m = 59;
	}
	return ret;
}

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : ConvYM_D                                                    */
/*  機能 : YM_D日付から年、月、日を生成する                            */
/*  引数 : IN  :    in_YM   : 0年からの月数                            */
/*                            <=0 なら、YYYY=0 MM=01 になる            */
/*                  in_D    : 日 <1 なら、1 に、                       */
/*                               >その月の最終日 なら、その月の最終日  */
/*                                 になる                              */
/*         OUT :    ymda()  : ymda(0) = 年                             */
/*                            ymda(1) = 月                             */
/*                            ymda(2) = 日                             */
/*  返却 : チェック結果 = 0    正常                                    */
/*                      = &H01 日を修正した                            */
/*                      = &H02 月を修正した                            */
/*                      = &H04 年を修正した                            */
/*  作成 : 2016/12/26 Akito Kobayashi                                  */
/*  更新 :                                                             */
/***********************************************************************/
int ConvYM_D(in_YM,in_D,ymda)
int in_YM,in_D,ymda[];
{
	int v_Year,v_Month,ret;

	ret = 0;
	if (in_YM <= 0) {
		v_Year = 0;
		v_Month = 0;
		ret = 4;
	}
	else {
		v_Year = (in_YM - 1) / 12;
		v_Month = ((in_YM - 1) % 12) + 1;
	}
	return ret | axCheckDate(v_Year,v_Month,in_D,ymda);
}

char *axDateToChar(dat,datlen0,ymda,max_ymda,dlm)
int ymda[],max_ymda,datlen0;
char *dat,*dlm;
{
	int i,ymda2[6],val,len,m,len_dlm,datlen;
	char sval[16],dlm1[6],*pp;

	len = strlen(dlm);
	len_dlm = akxqmlen(dlm,len);
	if ((len_dlm==1 || len_dlm==2) && !instrichars(dlm,PC_DATE_TERM)) {
		m = akxqkanjilen2(dlm,len);
		memzcpy(dlm1,dlm,m);
		len_dlm = m;
		datlen =datlen0 - 1;
		pp = dat;
		*pp = '\0';
		val = ymda[0];
		if (val >= 0) sprintf(sval,"%04d",val);
		else strcpy(sval,"____");
		len = strlen(sval);
		if (datlen < len) return dat;
		memzcpy(pp,sval,len);
		datlen -= len;
		pp += len;
		for (i=1;i<=2;i++) {
			if (datlen < len_dlm) break;
			if (dat != pp) {
				memzcpy(pp,dlm1,len_dlm);
				datlen -= len_dlm;
				pp += len_dlm;
			}
			val = ymda[i];
			if (val >= 0)
				sprintf(sval,"%02d",val);
			else
				strcpy(sval,"__");
			len = strlen(sval);
			if (datlen < len) break;
			memzcpy(pp,sval,len);
			datlen -= len;
			pp += len;
		}
/*
printf("axDateToChar: dat=[%s] sval=[%s]\n",dat,sval);
*/
		if (!instrchars(dat,"0123456789")) *dat = '\0';
		if (max_ymda >= 5) {
			if (ymda[3] >= 0) {
				mem_cpy_int(ymda2,ymda+3,3);
				if (*dat) {
					if (datlen > 0) {
						*pp++ = ' ';
						datlen--;
					}
				}
				else datlen = 0;
				if (datlen > 0) axTimeToChar(pp,datlen+1,ymda2,dlm+m);
			}
/*
printf("axDateToChar: dat=[%s]\n",dat);
*/
		}
		akxttrim(0,dat,strlen(dat));
	}
	else {
		mem_cpy_int(ymda2,ymda,3);
		if (max_ymda >= 5)
			mem_cpy_int(ymda2+3,ymda+3,3);
		else 
			mem_set_int(ymda2+3,0,3);
		axDateTimeToChar(dat,datlen0,ymda2,dlm);
	}
	return dat;
}

char *axTimeToChar(dat,datlen0,hnsa,dlm)
int hnsa[],datlen0;
char *dat,*dlm;
{
	int i,len_dlm,ymda[6],val,datlen,m,len;
	char sval[16],dlm2[6],*p,*pp;

	datlen = datlen0 - 1;
	len = strlen(dlm);
	len_dlm = akxqmlen(dlm,len);
	if (len_dlm<=2 && !instrichars(dlm,PC_DATE_TERM)) {
		m = akxqkanjilen2(dlm,len);
		memzcpy(dlm2,dlm,m);
		pp = dat;
		*pp = '\0';
		if (len_dlm == 2) strcpy(dlm2,dlm+m);
		len_dlm = strlen(dlm2);
		for (i=0;i<=2;i++) {
			if (datlen < len_dlm) break;
			if (dat != pp) {
				memzcpy(pp,dlm2,len_dlm);
				datlen -= len_dlm;
				pp += len_dlm;
			}
			val = hnsa[i];
			if (val >= 0)
				sprintf(sval,"%02d",val);
			else
				strcpy(sval,"__");
			len = strlen(sval);
			if (datlen < len) break;
			memzcpy(pp,sval,len);
			datlen -= len;
			pp += len;
/*
printf("axTimeToChar: i=%d dat=[%s]\n",i,dat);
*/
		}
		strcat(dlm2,"_");
		akxtstrim(0,dat,strlen(dat),dlm2);
	}
	else {
		mem_set_int(ymda,-1,3);
		mem_cpy_int(ymda+3,hnsa,3);
		axDateTimeToChar(dat,datlen,ymda,dlm);
	}
	return dat;
}

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : axYM_DToDate                                                */
/*  機能 : YM_D日付から年月日(YYYY-MM-DD)を生成する                    */
/*         年月日は、1904-01-01〜9999-12-31に調整される                */
/*  引数 : IN  :    in_YM   : 1904年からの月数                         */
/*                            <=0    なら、YYYY=1904 MM=01             */
/*                            = 9999 なら、YYYY=9999 MM=12             */
/*                  in_D    : 日 <1 なら、1 に、                       */
/*                               >その月の最終日 なら、その月の最終日  */
/*                                 になる                              */
/*          Optional dlm   : 区切り記号 (default="/")                  */
/*         OUT : なし                                                  */
/*  返却 : 日付データ(YYYY/MM/DD)                                      */
/*  作成 : 2016/12/26 Akito Kobayashi                                  */
/*  更新 : 2017/05/08 Akito Kobayashi Mod 1900 -> 1904                 */
/***********************************************************************/
char *axYM_DToDate(buf,buflen,in_YM,in_D,dlm)
int in_YM,in_D,buflen;
char *buf,*dlm;
{
	int v_Year,v_Month,ymda[3],ret;

	if (!dlm) dlm = "/";

	if (in_YM <= 0) {
		v_Year = 1904;
		v_Month = 1;
	}
	else if (in_YM = 99999) {
		v_Year = 2999;
		v_Month = 12;
	}
	else {
		v_Year = 1904 + (in_YM - 1) / 12;
		v_Month = ((in_YM - 1) % 12) + 1;
		if (v_Year > 99999) v_Year = 99999;
	}

	ret = axCheckDate(v_Year,v_Month,in_D,ymda);
	return axDateToChar(buf,buflen,ymda,3,dlm);
}

char *axDateTimeToChar(char *buf,int buflen,int ymda[],char *ymd_form)
{
	int ret,nymda[11],len;
	char  *kymda[11],*mymda[11];

	len = buflen/2;
	ret = anal_date_format(ymd_form,10,nymda,kymda,mymda,buf+len+1,len);
	return edit_date_by_anal_format(buf,len,ymda,ret,nymda,kymda,mymda);
}

int axToDate(ymda,ymdhns,ymd_form)
int ymda[];
char *ymdhns,*ymd_form;
{
	int ret,i,val,len_k,pos,n,hmsa[3],nymd,nymda[11],len;
	char *kymda[11],*mymda[11],ymd[128],c,*kymd,*p,wrk[128],buf[128];

	ret = 0;
	ymda[0] = 1900;
	ymda[1] = 1;
	ymda[2] = 1;
	ymda[3] = 0;
	ymda[4] = 0;
	ymda[5] = 0;
	strcpy(ymd,ymdhns);
	nymd = anal_date_format(ymd_form,10,nymda,kymda,mymda,buf,sizeof(buf));
	for (i=0;i<nymd;i++) {
		kymd = kymda[i];
		len_k = strlen(kymd);
		if (len_k > 0) {
			memzcpy(wrk,ymd,len_k);
			if (strcmp(wrk,kymd)) {
				ret = -1;
				break;
			}
			strcpy(ymd,ymd+len_k);
		}
		p = mymda[i];
		if (!strcmp(p,"MI")) c = 'N';
		else c = *p;
		n = nymda[i];
		kymd = kymda[i+1];
		if (n > 0) {
			if (!*ymd) {
				ret = -2;
				break;
			}
			if (*kymd) {
				len = strlen(ymd);
				pos = akxnskipin(ymd,len,"0123456789");
				if (pos >= len) {
					ret = -3;
					break;
				}
			}
			else pos = n;
			val = atoi2(ymd,pos);
			strcpy(ymd,ymd+pos);
			pos = instrchar(PC_DATE_TERM,c);
			ymda[pos-1] = val;
		}
	}
	kymd = kymda[nymd];
	len_k = strlen(kymd);
/*
printf("axToDate: len_k=%d kymda[%d]=[%s] ymd=[%s]\n",len_k,nymd,kymd,ymd);
*/
	if (len_k>0 && strcmp(ymd,kymd)) ret = -4;
	if (!ret) {
		val = axCheckDate(ymda[0],ymda[1],ymda[2],ymda);
		if (val) ret = val;
		val = axCheckTime(ymda[3],ymda[4],ymda[5],hmsa);
		mem_cpy_int(ymda+3,hmsa,3);
		if (val) ret = ret | (val * 16);
	}
	return ret;
}

int anal_date_format(ymd_form,max_nymd,nymda,kymda,mymda,buf,buflen0)
char *ymd_form;
int max_nymd,nymda[];
char *kymda[],*mymda[],*buf;
int buflen0;
{
	char ymd[64],wrk[64],c,cc,bc,ca[8],bca[8],cca[8],date_term_i[10],*p,*w;
	int i,i1,pos,inymd,ikymd,disp,len_ymd,ny,m,len,buflen,buflen1;
/*
printf("anal_date_format:Enter max_nymd=%d buflen0=%d\n",max_nymd,buflen0);
*/
	if (!ymd_form || max_nymd<=0) return -1;
	if (!nymda || !kymda || !mymda) return -2;
	if (!buf || buflen0<=1) return -3;
	p = buf;
	buflen = buflen0 - 1;
	mem_set_int(nymda,0,max_nymd+1);
	mem_set_addr(kymda,NULL,max_nymd+1);
	mem_set_addr(mymda,NULL,max_nymd+1);
	if (!ymd_form)
		ymd_form = PC_SYS_DATE_FORMAT;
	else if (!*ymd_form)
		ymd_form = PC_SYS_DATE_FORMAT;
	else {
		len_ymd = strlen(ymd_form);
		akxcuppern(ymd,ymd_form,len_ymd);
		if (len_ymd <= 2 && strcmp(ymd,"MI") && !instrchars(ymd,PC_DATE_TERM)) {
			c = ymd_form[0];
			cc = ymd_form[1];
			sprintf(wrk,"YYYY%cMM%cDD HH%cMI%cSS",c,c,cc,cc);
			ymd_form = wrk;
		}
	}
	len_ymd = strlen(ymd_form);
	if (buflen < len_ymd) return -4;
	akxcuppern(ymd,ymd_form,len_ymd);
/*
printf("anal_date_format: len_ymd=%d ymd=[%s]\n",len_ymd,ymd);
*/
	i = i1 = 1;
	disp = inymd = ikymd = 0;
	sprintf(date_term_i,"%s%c",PC_DATE_TERM,'I');
	bca[0] = '\0';
	while (i<=len_ymd && inymd<=max_nymd) {
		m = akxqkanjilen2(ymd+i-1,len_ymd-i+1);
		memzcpy(ca,ymd+i-1,m);
		pos = 0;
/*
printf("anal_date_format: i=%d m=%d ca=[%s]\n",i,m,ca);
*/
		if (m == 1) {
			c = ca[0];
			pos = instrchar(date_term_i,c);
			if (c == 'H') {
				memzcpy(cca,ymd+i-1,3);
				if (!strcmp(cca,"H24") || !strcmp(cca,"H12")) strcpy(ca,cca);
			}
		}
		buflen1 = buflen + 1;
		if (!disp) {
			if (ca[0] == '\\') {
				i++;
				m = akxqkanjilen2(ymd+i-1,len_ymd-i+1);
				memzcpy(ca,ymd+i-1,m);
			}
			else if (pos > 0) {
				disp = 1;
				ny = 1;
				len = i - i1;
				if (len > buflen) return -11;
				len = akxcreplace_opt2(p,buflen1,ymd_form+i1-1,len,"\\","",0);
/*
printf("anal_date_format: i1=%d p=[%s]\n",i1,p);
*/
				kymda[ikymd] = p;
				ikymd++;
				mymda[inymd] = Strdup(ca);
				strcpy(bca,ca);
				len++;
				p += len;
				buflen -= len;
			}
		}
		else if (disp == 1) {
			if (!pos) {
				disp = 0;
				nymda[inymd] = ny;
				inymd = inymd + 1;
				if (ca[0] == '\\') {
					i++;
					m = akxqkanjilen2(ymd+i-1,len_ymd-i+1);
					memzcpy(ca,ymd+i-1,m);
				}
				i1 = i;
			}
			else {
				if (strcmp(bca,ca) && (strcmp(bca,"M") || strcmp(ca,"I"))) {
					nymda[inymd] = ny;
					inymd = inymd + 1;
					disp = 1;
					ny = 1;
					len = i - i1;
					if (len > buflen) return -12;
					len = akxcreplace_opt2(p,buflen1,ymd_form+i1-1,len,"\\","",0);
/*
printf("anal_date_format: i1=%d p=[%s]\n",i1,p);
*/
					kymda[ikymd] = p;
					ikymd++;
					mymda[inymd] = Strdup(ca);
					strcpy(bca,ca);
					len++;
					p += len;
					buflen -= len;
				}
				else {
					ny++;
					len = strlen(ca);
					w = mymda[inymd];
/*
printf("anal_date_format: bca=[%s] w=[%s] ca=[%s]\n",bca,w,ca);
*/
					if (w) len += strlen(w);
					if (len > buflen) return -13;
					if (w) strcpy(p,w);
					else *p = '\0';
					strcat(p,ca);
					mymda[inymd] = p;
					len++;
					p += len;
					buflen -= len;
				}
			}
		}
		i += strlen(ca);
	}
	if (!disp) {
		len = len_ymd - i1 + 1;
		if (len <= buflen) {
			akxcreplace_opt2(p,buflen+1,ymd_form+i1-1,len,"\\","",0);
			kymda[ikymd] = p;
/*
printf("anal_date_format: i1=%d p=[%s]\n",i1,p);
*/
		}
		else return -14;
	}
	else if (disp == 1) {
		nymda[inymd] = ny;
		inymd++;
	}
/*
printf("anal_date_format:Exit inymd=%d buflen=%d\n",inymd,buflen);
*/
	return inymd;
}

char *edit_date_by_anal_format(buf,buflen0,ymda,inymd,nymda,kymda,mymda)
int ymda[],inymd,nymda[],buflen0;
char *buf,*kymda[],*mymda[];
{
	char  c,*p,*dat,*kymd,*ymd_str,*rdelpat,*ldelpat,wrk[64],*pp;
	int val,i,n,pos,del_ymd,del_mask,m_bit,len,buflen;
	int rdelpat_len,ldelpat_len,dat_len,ymd_str_len;

	if (!buf) return NULL;
	*buf = '\0';
	if (!ymda || !nymda || !kymda || !mymda) return buf;
	if (buflen0<=1) return buf;
	pp = buf;
	buflen = buflen0 - 1;
	rdelpat = Malloc(1);
	ldelpat = Malloc(1);
	dat = Malloc(1);
	ymd_str = Malloc(1);
	*rdelpat = '\0';
	*ldelpat = '\0';
	*dat = '\0';
	*ymd_str = '\0';
	del_ymd = del_mask = 0;
	rdelpat_len = ldelpat_len = dat_len = ymd_str_len = 0;
	for (i=0;i<inymd;i++) {
		p = mymda[i];
		if (!strcmp(p,"MI")) c = 'N';
		else c = *p;
		n = nymda[i];
		kymd = kymda[i + 1];
		if (i <= 2) {
			ldelpat_len += strlen(kymd);
			ldelpat = Realloc(ldelpat,ldelpat_len+1);
			strcat(ldelpat,kymd);
			if (n > 0) del_mask += m_bit;
		}
		else {
			rdelpat_len += strlen(kymd);
			rdelpat = Realloc(rdelpat,rdelpat_len+1);
			strcat(rdelpat,kymd);
		}
		if (n > 0) {
			*dat = '\0';
			pos = instrchar(PC_DATE_TERM, c);
			if (pos > 0) {
				val = ymda[pos-1];
				if (val >= 0) {
					if (pos = 1) {
						sprintf(dat,"0000%d",val);
						len = strlen(dat);
						if (n==2 || (n>1 && (len-4)<=n))
							strcpy(dat,dat+len-n);
					}
					else {
						sprintf(dat,"00%d",val);
						len = strlen(dat);
						if (n>1 && (len-2)<=n)
							strcpy(dat,dat+len-n);
					}
				}
				else {
					del_ymd += m_bit;
					if (pos == 1) {
						sprintf(dat,"____%s","_");
						len = strlen(dat);
						if (n==2 || (n>1 && (len-4)<=n))
							strcpy(dat,dat+len-n);
					}
					else {
						sprintf(dat,"__%d",val);
						len = strlen(dat);
						if (n>1 && (len-2) <= n)
							strcpy(dat,dat+len-n);
					}
				}
				dat_len += strlen(kymd);
				dat = Realloc(dat,dat_len+1);
				strcat(dat,kymd);
			}
		}
		else {
			dat_len = strlen(kymd);
			dat = Realloc(dat,dat_len+1);
			strcpy(dat,kymd);
		}
		ymd_str_len += strlen(dat);
		ymd_str = Realloc(ymd_str,ymd_str_len+1);
		strcat(ymd_str,dat);
		m_bit = m_bit + m_bit;
	}
	akxtstrim(1,ymd_str,strlen(ymd_str),rdelpat);
	if ((del_ymd & del_mask) == del_mask)
		akxtstrim(2,ymd_str,strlen(ymd_str),ldelpat);
	else {
		dat_len = strlen(ymd_str);
		dat = Realloc(dat,dat_len+1);
		strcpy(dat,ymd_str);
		ymd_str_len = strlen(kymda[0]) + strlen(dat);
		ymd_str = Realloc(ymd_str,ymd_str_len+1);
		strcpy(ymd_str,kymda[0]);
		strcat(ymd_str,dat);
	}
	akxttrim(0,ymd_str,strlen(ymd_str));
	strnzcpy(buf,ymd_str,buflen-1);
/*
	printf("edit_date_by_anal_format: dat_len=%d dat=[%s]\n",dat_len,dat);
	printf("edit_date_by_anal_format: ymd_str_len=%d ymd_str=[%s]\n",ymd_str_len,ymd_str);
	printf("edit_date_by_anal_format: rdelpat_len=%d rdelpat=[%s]\n",rdelpat_len,rdelpat);
	printf("edit_date_by_anal_format: ldelpat_len=%d ldelpat=[%s]\n",ldelpat_len,ldelpat);
*/
	Free(dat);
	Free(ymd_str);
	Free(rdelpat);
	Free(ldelpat);
	return buf;
}

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : get_date_term_no                                            */
/*  機能 : 期間文字列から期間番号を求める                              */
/*  引数 : IN  :    term    : 期間文字列 (大文字小文字を問わない)      */
/*                            term と以下を相互に前方一致で比較する    */
/*                            "YEAR"   or "Y"      を含むとき、年      */
/*                            "MONTH"  or "M"      を含むとき、月      */
/*                            "DAY"    or "D"      を含むとき、日      */
/*                            "HOUR"   or "H"      を含むとき、時      */
/*                            "MINUTE" or "N","MI" を含むとき、分      */
/*                            "SECOND" or "S"      を含むとき、秒      */
/*  返却 : 期間番号 : 1 〜 6 = 年,月,日,時,分,秒,に対応する            */
/*  作成 : 2017/01/25 Akito Kobayashi                                  */
/*  更新 :                                                             */
/***********************************************************************/
int get_date_term_no(char *term)
{
	static char *stra[] = {"YEAR","MONTH","DAY","HOUR","MINUS","SECOND",NULL};
	int pos,posa[2];

	if (!term) term = "D";
	if (!*term) term = "D";
	pos = akxs_seqr_str_grp(stra,-1,term,0x01|0x08,posa);
	if (!pos)  pos = instrichar(PC_DATE_TERM,*term);
	return pos;
}

char *get_sysdate_ymd(ymda,max_ymda,term)
int ymda[],max_ymda;
char *term;
{
	char *ymd,dlma[3];
	int ret,pos;

	ymd = akx_log_time();
	ret = axConvDate(ymd,ymda,max_ymda,dlma,2);
	if (*term) {
		pos = get_date_term_no(term);
		if (pos >0 && pos<6) {
			mem_set_int(ymda+pos-1,-1,6-pos);
		}
	}
	return ymd;
}

char *axGetSysDate(term)
char *term;
{
	int ymda[6];

	if (!term) term = "";
	return get_sysdate_ymd(ymda,6,term);
}

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : axDateDiff                                                  */
/*  機能 : 時間間隔で日時の差を求める。(ymd1-ymd2)                     */
/*         月を除き時間間隔未満は切捨てられる。                        */
/*         月のときは日にちをその月の日数で割った値の差が加わる        */
/*  引数 : IN  :    term    : 時間間隔 (Y,M,D,H,MI(N),Sで始まる文字列) */
/*                  ymda1() : 日時1                                    */
/*                            ymda1(0) = 年 Y                          */
/*                            ymda1(1) = 月 M                          */
/*                            ymda1(2) = 日 D                          */
/*                            ymda1(3) = 時 H                          */
/*                            ymda1(4) = 分 MI or N                    */
/*                            ymda1(5) = 秒 S                          */
/*                  ymda2() : 日時2                                    */
/*                            内容は日時1と同じ                        */
/*         OUT : なし                                                  */
/*  返却 : 時間間隔の差                                                */
/*  作成 : 2017/08/18 Akito Kobayashi                                  */
/*  更新 : 2020/02/20 Akito Kobayashi Mod 日数を正しく計算             */
/***********************************************************************/
double axDateDiff(term,ymda1,ymda2)
char *term;
int ymda1[],ymda2[];
{
	char *ymd,dlma[3];
	int i,m,sig,n,u[6],ymd1[6],ymd2[6],t1,t2,ret;
	double tt1,tt2,m1,m2;

	n = get_date_term_no(term);
/*
printf("axDateDiff: n=%d\n",n);
*/
	mem_cpy_int(ymd1,ymda1,6);
	mem_cpy_int(ymd2,ymda2,6);
	ret = axAddToDate(ymd1,6,term,0);
	ret = axAddToDate(ymd2,6,term,0);
	for (i=0;i<6;i++) {
		sig = ymd1[i] - ymd2[i];
		if (sig) break;
	}
/*
printf("axDateDiff: i=%d sig=%d\n",i,sig);
*/
	if (n==1 || !sig) {
		tt1 = sig;
		tt2 = 0.0;
	}
	else if (n == 2) {
		u[0] = 0;
		u[1] = 12;
		tt1 = 0.0;
		tt2 = 0.0;
		i = X_MIN(ymd1[0],ymd2[0]);
		tt1 = ymd1[0] - i;
		tt2 = ymd2[0] - i;
		tt1 = tt1 * u[1] + ymd1[1];
		tt2 = tt2 * u[1] + ymd2[1];
/*
printf("axDateDiff: tt1=%f tt2=%f\n",tt1,tt2);
*/
		/* 時間間隔が、月のときの日数差による補正 */
		if (n == 2) {
			m1 = get_day_num(ymd1[0],ymd1[1],0);
			m2 = get_day_num(ymd2[0],ymd2[1],0);
			tt1 = tt1 + ymd1[2]/m1 - ymd2[2]/m2 + 0.005;
		}
		tt1 = tt1 - tt2;
	}
	else {
		u[2] = 30;
		u[3] = 24;
		u[4] = 60;
		u[5] = 60;
		if (sig < 0) {
			for (i=0 ;i<=n-1;i++) {
				m = ymd1[i];
				ymd1[i] = ymd2[i];
				ymd2[i] = m;
			}
		}
		tt1 = 0.0;
		tt2 = 0.0;
		for (i=ymd2[0];i<=ymd1[0]-1;i++) {
			tt1 = tt1 + 365;
			if (akxc_is_leap_year(i)) tt1 = tt1 + 1;
		}
/*
printf("axDateDiff: tt1=%f tt2=%f\n",tt1,tt2);
*/
		t1 = get_day_num(ymd1[0],ymd1[1],ymd1[2]);
		t2 = get_day_num(ymd2[0],ymd2[1],ymd2[2]);
/*
printf("axDateDiff: t1=%d t2=%d\n",t1,t2);
*/
		tt1 = tt1 + t1 - t2;
		for (i=3;i<=n-1;i++) {
			tt1 = tt1 * u[i] + ymd1[i];
			tt2 = tt2 * u[i] + ymd2[i];
/*
printf("axDateDiff: i=%d tt1=%f tt2=%f\n",i,tt1,tt2);
*/
		}
		tt1 = tt1 - tt2;
		if (sig < 0) tt1 = -tt1;
	}
	return tt1;
}

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : get_str_diff_time	*/
/*  機能 : 時間間隔での日時の差から日数と時分秒の文字列を求める｡	*/
/*  引数 : IN      : term     : 時間間隔(Y,M,D,H,MI,N,Sで始まる文字列)	*/
/*                                年: 365日で換算する｡	*/
/*                                月: 30日で換算する。	*/
/*                   tt       : 日時の差	*/
/*                   hmsa()   : hmsa(0) = 時	*/
/*                              hmsa(1) = 分	*/
/*                              hmsa(2) = 秒	*/
/*                   Day      : 日数	*/
/*  返却 : 日数と時分秒の文字列	*/
/*  作成 : 2018/12/27 Akito Kobayashi	*/
/*  更新 :	*/
/***********************************************************************/
char *get_str_diff_time(term,tt,hmsa,day) 
char *term;
double tt;
int hmsa[];
double day;
{
	static char dat[64];
	int i,ii,n,d;
	double intval[3],ttt,val;

	*dat = '\0';
	hmsa[0] = 0;
	hmsa[1] = 0;
	hmsa[2] = 0;
	day = 0.0;
	n = get_date_term_no(term);
	if (n>0 && tt>= 0.0) {
		if (n == 1)
			day = tt * 365.0;
		else if (n == 2)
			day = tt * 30.0;
		else if (n == 3)
			day = tt;
		else {
			intval[0] = 60.0;
			intval[1] = 60.0;
			intval[2] = 24.0;
			ii = 6 - n;
			for (i=ii;i<=2;i++) {
#if 1
				ttt = tt;
				val = intval[i];
				while (ttt >= val) {
					ttt -= val;
				}
				hmsa[2-i] = ttt;
				tt = (tt-ttt) / val;
#else
				if (tt > intval[i])
					hmsa[2-i] = tt % intval[i];
				else
					hmsa[2-i] = tt;
				tt = tt / intval[i];
#endif
			}
			day = tt;
		}
		*dat = '\0';
		if (day > LONG_MAX)
			strcpy(dat," 日 ");
		else {
			d = day;
			if (d>0 || n<=3) sprintf(dat+strlen(dat),"%d 日 ",d);
		}
		if (n>=4 && hmsa[0]>0) sprintf(dat+strlen(dat),"%d 時間 ",hmsa[0]);
		if (n>=5 && hmsa[1]>0) sprintf(dat+strlen(dat),"%d 分 ",hmsa[1]);
		if (n>=6) sprintf(dat+strlen(dat),"%d 秒",hmsa[2]);
	}
	return dat;
}

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : get_day_num	*/
/*  機能 : yyyy年のmm/ddまでの日数、または、その月の日数を求める	*/
/*             dd >  0 : yyyy年のmm/ddまでの日数	*/
/*                       mm <= 0 : ddを返す	*/
/*             dd <= 0 : yyyy/mmの日数、	*/
/*                       mm <= 0 : 0を返す	*/
/*  引数 : IN     : yyyy     : 年	*/
/*                               <= 0 : うるう年でないと見なす	*/
/*                  mm       : 月	*/
/*                  dd       : 日	*/
/*  返却 : 日数	*/
/*  作成 : 2018/07/XX Akito Kobayashi	*/
/*  更新 : 2018/07/17 Akito Kobayashi Add if dd=0	*/
/******************************************************************/
int get_day_num(yyyy,mm,dd)
int yyyy,mm,dd;
{
	static uchar mon[12]={31,28,31,30,31,30,31,31,30,31,30,31};
	int i,d,leap;

	if (yyyy < 0) yyyy = 0;
	if (mm < 1) mm = 1;
	else if (mm > 12) mm = 12;

	leap = akxc_is_leap_year(yyyy);

	if (dd > 0) {
		d += dd;
		for (i=0;i<mm-1;i++) {
			d = d + mon[i];
		}
		if (mm>=2 && leap) d++;
	}
	else {
		d = mon[mm-1];
		if (mm==2 && leap) d++;
	}
	return d;
}

/********1*********2*********3*********4*********5*********6*********7**/
/*  名称 : axLastDay	*/
/*  機能 : yyyy/mm/ddの月の最後の日を求める	*/
/*  引数 : IN     : ymda()  : ymda(0) = 年	*/
/*                            ymda(1) = 月	*/
/*                            ymda(2) = 日	*/
/*  返却 : 最後の日	*/
/*  作成 : 2019/10/01 Akito Kobayashi	*/
/*  更新 :	*/
/******************************************************************/
int axLastDay(ymda)
int ymda[];
{
	return get_day_num(ymda[0],ymda[1],0);
}
