日期格式的伟大革新--关于日期格式的压缩算法--减少月份占两位格的表示法
原创:李均宇 2023-01-09于吴川梅菉 2123-09
众所周知,日期格式通用表示法是,四位年份,两位月份,两位日期
忽发奇想,这可不可以更加简化呢?忽然发现,果然是可行的!!!
因为,世纪数,当前不是19就是20,而月份,仅12个,将月份与世纪数全并,是可行的。
算法:
1,如果世纪数的第一位是2,表是是20,世纪数减2即是月份数,如果世纪数的开头是3,表示也是世纪数20,一样世纪数减2即是月份数
2,如果世纪数的第一位是1,表示是19,世纪数尾数减9,就是月份数,如果世纪数第一位是0,表示是19,世纪数尾数减9,得到个位数,再加一个十位数,就表示月份
3,如果世纪数开头数字是4,5,表示是18的,为4,则减8,为5,则减8后再加一个十位数
4,如果世纪数开头数字是6,7,表示是21,为6,尾数减1,为月份数,为7,尾数减1后加一个十位数,为月份数
5,如果世纪数开头数字是8,9,表示是22,以此类推
举例:
1,2023-01-09-->2123-09-->20...01 2023-11-09-->3123-09-->2023-11
2, 1923-01-09-->1023-09-->19...01 1923-11-09-->0023-09-->1923-01
3, 1823-01-09-->4923-09-->18...01 1823-11-09-->5923-09-->1823-11
4,2123-01-09-->6223-09-->21...01 2123-11-09-->7223-09-->2123-11
5,2223-01-09-->8323-09-->22...01 2223-11-09-->9323-09-->2223-11
这种方法可以表示五百年,可以将日期减少两格,估计应用量数以亿计,应用量是天文单位,是历史性的巨大革新,甚至用于身份证号码
这种表示法,可以用于日期,但用于时间,就行不通了,将小时与分钟用此算法,无法压缩。
下面的代码已经在pascal中测试通过,如果要反向解析,也不是难事,时间紧,暂不理会了。且算法字头可以自行另设的。
procedure TForm1.Button1Click(Sender: TObject);
var
y1, y2, y3, y4, month1, month2, day: string;
y12, y34, y1_temp, y2_temp: string;
begin
y1 := edit1.Text[1];
y2 := edit1.Text[2];
y3 := edit1.Text[3];
y4 := edit1.Text[4];
month1 := edit2.Text[1];
month2 := edit2.Text[2];
day := edit3.Text;
y34 := y3 + y4;
///18
if y1 + y2 = '18' then
begin
if month1 = '0' then
begin
y1_temp := '4';
y2_temp := inttostr(8 + strtoint(month2))[2];
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '5';
y2_temp := inttostr(8 + strtoint(month2))[2];
y12 := y1_temp + y2_temp;
end;
end;
///18
///19
if y1 + y2 = '19' then
begin
if month1 = '0' then
begin
y1_temp := '1';
y2_temp := (inttostr(9 + strtoint(month2)))[2];
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '0';
y2_temp := inttostr(9 + strtoint(month2))[2];
y12 := y1_temp + y2_temp;
end;
end;
///19
///20
if y1 + y2 = '20' then
begin
if month1 = '0' then
begin
y1_temp := '2';
y2_temp := inttostr(0 + strtoint(month2))[2];
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '3';
y2_temp := inttostr(0 + strtoint(month2))[2];
y12 := y1_temp + y2_temp;
end;
end;
///20
///21
if y1 + y2 = '21' then
begin
if month1 = '0' then
begin
y1_temp := '6';
y2_temp := inttostr(1 + strtoint(month2))[2];
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '7';
y2_temp := inttostr(1 + strtoint(month2))[2];
y12 := y1_temp + y2_temp;
end;
end;
///21
///22
if y1 + y2 = '22' then
begin
if month1 = '0' then
begin
y1_temp := '8';
y2_temp := inttostr(2 + strtoint(month2))[2];
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '9';
y2_temp := inttostr(2 + strtoint(month2))[2];
y12 := y1_temp + y2_temp;
end;
end;
///22
showmessage(y12 + y34 + '-' + day);
end;
============================================
改进算法:(更加容易心算)
1,如果世纪数的第一位是2,表是是20,世纪尾数即是月份数,如果世纪数的开头是3,表示也是世纪数20,世纪尾数即是月份尾数,月份十位数置1
2,如果世纪数的第一位是1,表示是19,世纪尾数即是月份数,如果世纪数第一位是0,表示是19,世纪尾数即是月份尾数,月份十位数置1
3,如果世纪数开头数字是4,5,表示是18的,为4,则世纪数即是月份尾数,为5,世纪尾数即是月份尾数,月份十位数置1
4,如果世纪数开头数字是6,7,表示是21,为6,则世纪数即是月份尾数,为7,世纪尾数即是月份尾数,月份十位数置1
5,如果世纪数开头数字是8,9,表示是22,为8,则世纪数即是月份尾数,为9,世纪尾数即是月份尾数,月份十位数置1
举例:
1,2023-09-09==2923-09 2023-11-09==3123-09
2, 1923-09-09==1923-09 1923-11-09==0123-09
3, 1823-09-09==4923-09 1823-11-09==5923-09
4,2123-09-09==6923-09 2123-11-09==7223-09
5,2223-09-09==8923-09 2223-11-09==9323-09
1)这种方法可以表示五百年,对于跨世纪时的日期有用。如果日的开头由原来的0,1,2,3,扩展成4,5,6,7,则可以表示一千年。且容易心算。如果采用序号法,则最多可达三千年上下。对于有时因为日期格式文本超长带来的麻烦,估计有用的。
2)例如EXCEL数值最长15位,将身份证减少两位,成了16位,最后一位检较码可以不用录入,自动算出来即时核对下,在不太严格时,EXCEl可以一列存贮,或者用两列,第二列保存最后一位检较码等等。。。
3)下面的代码已经在pascal中测试通过,如果要反向解析,也不是难事,时间紧,暂不理会了。且算法字头可以自行另设的。
procedure TForm1.Button1Click(Sender: TObject);
var
y1, y2, y3, y4, month1, month2, day: string;
y12, y34, y1_temp, y2_temp: string;
begin
y1 := edit1.Text[1];
y2 := edit1.Text[2];
y3 := edit1.Text[3];
y4 := edit1.Text[4];
month1 := edit2.Text[1];
month2 := edit2.Text[2];
day := edit3.Text;
y34 := y3 + y4;
///18
if y1 +y2= '18' then
begin
if month1 = '0' then
begin
y1_temp := '4';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '5';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
end;
///18
///19
if y1 + y2 = '19' then
begin
if month1 = '0' then
begin
y1_temp := '1';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '0';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
end;
///19
///20
if y1 + y2 = '20' then
begin
if month1 = '0' then
begin
y1_temp := '2';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '3';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
end;
///20
///21
if y1 + y2 = '21' then
begin
if month1 = '0' then
begin
y1_temp := '6';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '7';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
end;
///21
///22
if y1 + y2 = '22' then
begin
if month1 = '0' then
begin
y1_temp := '8';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
if month1 = '1' then
begin
y1_temp := '9';
y2_temp := month2;
y12 := y1_temp + y2_temp;
end;
end;
///22
showmessage(y12 + y34 + '-' + day);
end;
改进算法:百年内的日期可以缩为五位数表示的算法
年份四位,月份两位,日期两位,共八位
如果仅表示一百年内的日期,可以减少三位,变成五位,算法如下
1)去掉世纪数,百年内,可以跨世纪,比如如果是大于30表示1930以后,小于30,表示2030以前的日期
2)将月份的十位数去掉,用日期来标志FLAG代替,如日期开头是0,1,2,3,表示月份是小于10的,如果日期开头是6,7,8,9,表示月份是大于9的。
这样的算法,就可以把百年内的日期压缩进五位数,且易心算算出来,不用借助工具
3)下面的代码已经在pascal中测试通过,如果要反向解析,也不是难事,时间紧,暂不理会了。且算法字头可以自行另设的。
procedure TForm1.Button1Click(Sender: TObject);
var
month1, month2: string;
y1234,y34, d1_temp, d2_temp: string;
begin
y1234 := edit1.Text;
y34 := edit1.Text[3] + edit1.Text[4];
month1 := edit2.Text[1];
month2 := edit2.Text[2];
d1_temp := edit3.Text[1]; //day
d2_temp := edit3.Text[2]; //day
if y1234 >= '1930' then
begin
if month1 = '1' then
begin
if d1_temp = '0' then d1_temp := '6';
if d1_temp = '1' then d1_temp := '7';
if d1_temp = '2' then d1_temp := '8';
if d1_temp = '3' then d1_temp := '9';
end;
end;
if y1234 < '2030' then
begin
if month1 = '1' then
begin
if d1_temp = '0' then d1_temp := '6';
if d1_temp = '1' then d1_temp := '7';
if d1_temp = '2' then d1_temp := '8';
if d1_temp = '3' then d1_temp := '9';
end;
end;
if y1234 >= '1930' then
if y1234 < '2030' then
showmessage(y34 + '-' + month2 + '-' + d1_temp + d2_temp);
end;
===================================================
改进算法:千年内的日期可以缩为六位数表示的算法
百年内的日期可以缩为五位数表示的算法,在这个基础上,加多一个标志位,世纪数,就可以轻易表示千年,可读性高易心算
年份四位,月份两位,日期两位,共八位
如果仅表示一百年内的日期,可以减少三位,变成五位,算法如下
1)千年内世纪数用一个数字表示,可以跨世纪,比如如果是大于3表示1300以后,小于3,表示2300以前的日期
2)将月份的十位数去掉,用日期来标志FLAG代替,如日期开头是0,1,2,3,表示月份是小于10的,如果日期开头是6,7,8,9,表示月份是大于9的。
这样的算法,就可以把千年内的日期可以缩为六位数,且可读性高易心算算出来,不用借助工具
3)下面的代码已经在pascal中测试通过。且算法字头可以自行另设的。
procedure TForm1.Button1Click(Sender: TObject);
var
month1, month2: string;
y1234, y234, d1_temp, d2_temp: string;
begin
y1234 := edit1.Text;
y234 := edit1.Text[2] +edit1.Text[3] + edit1.Text[4];
month1 := edit2.Text[1];
month2 := edit2.Text[2];
d1_temp := edit3.Text[1]; //day
d2_temp := edit3.Text[2]; //day
if y1234 >= '1300' then
begin
if month1 = '1' then
begin
if d1_temp = '0' then d1_temp := '6';
if d1_temp = '1' then d1_temp := '7';
if d1_temp = '2' then d1_temp := '8';
if d1_temp = '3' then d1_temp := '9';
end;
end;
if y1234 < '2300' then
begin
if month1 = '1' then
begin
if d1_temp = '0' then d1_temp := '6';
if d1_temp = '1' then d1_temp := '7';
if d1_temp = '2' then d1_temp := '8';
if d1_temp = '3' then d1_temp := '9';
end;
end;
if y1234 >= '1300' then
if y1234 < '2300' then
begin
edit4.Text := y234;
edit5.Text := month2;
edit6.Text := d1_temp + d2_temp;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
month1, month2: string;
y1234, y234,y2, d1_temp, d2_temp: string;
begin
y234 := edit4.Text;
y2:= edit4.Text[1];
month2 := edit5.Text;
d1_temp := edit6.Text[1]; //day
d2_temp := edit6.Text[2]; //day
if y2 >= '3' then
begin
y234 := '1' + y234;
month1 := '0';
if d1_temp = '6' then
begin
d1_temp := '0';
month1 := '1';
end;
if d1_temp = '7' then
begin
d1_temp := '1';
month1 := '1';
end;
if d1_temp = '8' then
begin
d1_temp := '2';
month1 := '1';
end;
if d1_temp = '9' then
begin
d1_temp := '3';
month1 := '1';
end;
end;
if y2 < '3' then
begin
y1234 := '2' + y234;
month1 := '0';
if d1_temp = '6' then
begin
d1_temp := '0';
month1 := '1';
end;
if d1_temp = '7' then
begin
d1_temp := '1';
month1 := '1';
end;
if d1_temp = '8' then
begin
d1_temp := '2';
month1 := '1';
end;
if d1_temp = '9' then
begin
d1_temp := '3';
month1 := '1';
end;
end;
if y1234 >= '1300' then
if y1234 < '2300' then
begin
edit1.Text := y1234;
edit2.Text := month1 + month2;
edit3.Text := d1_temp + d2_temp;
end;
end;
关于五位数的百年日期表示法的扩展
日期原本:y1y2y3y4-m1m2-d1m2
现在已知可以百年内缩为五位,y3y4-m2-d1d2
忽想到,可以上下扩展三十年,共160年的日期表示法,且易于心算,心算与排序序号相结合的方法
1)如果是主体的百年内,则适用心算法缩为五位数
2)如果是超出主体百年内的日期,在日期头置8或9,8可以为向下年份,9可以为向上年份。
然后,令y3y4m2d2这四个数失去原来意义,用于表示向下或向上的日数的序号,这个要用软件工具计出来的。
这样,最终,可以五位数表示160年日期,且主体百年易心算,非主流上下60年要计算。
这可用于身份证号码,人若过百岁,换身份证的号码,原号码是别人的了。过去第一代身份证号码主流不变,不用加长。或用尾数区分这日期是上下世纪,尾数部分可标志