mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
v2.7.2.1
This commit is contained in:
22
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_fmt_itm.java
Normal file
22
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_fmt_itm.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public interface Pft_fmt_itm {
|
||||
int TypeId();
|
||||
void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr);
|
||||
}
|
||||
189
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_fmt_itm_.java
Normal file
189
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_fmt_itm_.java
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Pft_fmt_itm_ {
|
||||
public static final int
|
||||
Tid_seg_int = 1
|
||||
, Tid_hour_base12 = 2
|
||||
, Tid_dow_base0 = 3
|
||||
, Tid_seg_str = 4
|
||||
, Tid_year_isLeap = 5
|
||||
, Tid_timestamp_unix = 6
|
||||
, Tid_raw_ary = 7
|
||||
, Tid_raw_byt = 8
|
||||
, Tid_dayOfYear = 9
|
||||
, Tid_daysInMonth = 10
|
||||
, Tid_AmPm = 11
|
||||
, Tid_roman = 12
|
||||
, Tid_iso_fmt = 13
|
||||
, Tid_rfc_5322 = 14
|
||||
, Tid_raw = 15
|
||||
, Tid_timezone_offset = 16
|
||||
, Tid_thai = 17
|
||||
, Tid_minguo = 18
|
||||
, Tid_hebrew_year_num = 21
|
||||
, Tid_hebrew_month_num = 20
|
||||
, Tid_hebrew_day_num = 19
|
||||
, Tid_hebrew_month_days_count = 22
|
||||
, Tid_hebrew_month_name_full = 23
|
||||
, Tid_hebrew_month_name_gen = 24
|
||||
, Tid_hebrew_numeral = 25
|
||||
;
|
||||
|
||||
public static final Pft_fmt_itm
|
||||
Year_len4 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_year , 4, Bool_.Y)
|
||||
, Year_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_year , 2, Bool_.Y)
|
||||
, Month_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_month , 2, Bool_.Y)
|
||||
, Month_int = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_month , 2, Bool_.N)
|
||||
, Day_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_day , 2, Bool_.Y)
|
||||
, Day_int = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_day , 2, Bool_.N)
|
||||
, Hour_base24_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_hour , 2, Bool_.Y)
|
||||
, Hour_base24 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_hour , 2, Bool_.N)
|
||||
, Hour_base12_len2 = new Pft_fmt_itm_hour_base12(Bool_.Y)
|
||||
, Hour_base12 = new Pft_fmt_itm_hour_base12(Bool_.N)
|
||||
, Minute_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_minute , 2, Bool_.Y)
|
||||
, Second_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_second , 2, Bool_.Y)
|
||||
, Dow_base1_int = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_dayOfWeek , 1, Bool_.Y)
|
||||
, Dow_base0_int = new Pft_fmt_itm_dow_base0()
|
||||
, WeekOfYear_int = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_weekOfYear , 2, Bool_.N)
|
||||
, WeekOfYear_int_len2 = new Pft_fmt_itm_seg_int(DateAdp_.SegIdx_weekOfYear , 2, Bool_.Y)
|
||||
, Month_abrv = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_month, Xol_msg_itm_.Id_dte_month_abrv_jan - Int_.Base1) // Jan
|
||||
, Month_name = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_month, Xol_msg_itm_.Id_dte_month_name_january - Int_.Base1) // January
|
||||
, Month_gen = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_month, Xol_msg_itm_.Id_dte_month_gen_january - Int_.Base1) // January
|
||||
, Dow_abrv = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_dayOfWeek, Xol_msg_itm_.Id_dte_dow_abrv_sun) // Sun
|
||||
, Dow_name = new Pft_fmt_itm_seg_str(DateAdp_.SegIdx_dayOfWeek, Xol_msg_itm_.Id_dte_dow_name_sunday) // Sunday
|
||||
, Year_isLeap = new Pft_fmt_itm_year_isLeap()
|
||||
, Timestamp_unix = new Pft_fmt_itm_timestamp_unix()
|
||||
, Byte_space = new Pft_fmt_itm_raw_byt(Byte_ascii.Space)
|
||||
, Byte_comma = new Pft_fmt_itm_raw_byt(Byte_ascii.Comma)
|
||||
, Byte_dash = new Pft_fmt_itm_raw_byt(Byte_ascii.Dash)
|
||||
, DayOfYear_int = new Pft_fmt_itm_dayOfYear()
|
||||
, DaysInMonth_int = new Pft_fmt_itm_daysInMonth()
|
||||
, AmPm_lower = new Pft_fmt_itm_am_pm(true)
|
||||
, AmPm_upper = new Pft_fmt_itm_am_pm(false)
|
||||
, Roman = new Pft_fmt_itm_roman()
|
||||
, Thai = new Pft_fmt_itm_thai()
|
||||
, Minguo = new Pft_fmt_itm_minguo()
|
||||
, Hebrew_year_num = new Pft_fmt_itm_hebrew_year_num()
|
||||
, Hebrew_month_num = new Pft_fmt_itm_hebrew_month_num()
|
||||
, Hebrew_day_num = new Pft_fmt_itm_hebrew_day_num()
|
||||
, Hebrew_month_days_count = new Pft_fmt_itm_hebrew_month_days_count()
|
||||
, Hebrew_month_name_full = new Pft_fmt_itm_hebrew_month_name_full()
|
||||
, Hebrew_month_name_gen = new Pft_fmt_itm_hebrew_month_name_gen()
|
||||
, Hebrew_numeral = new Pft_fmt_itm_hebrew_numeral()
|
||||
, Raw = new Pft_fmt_itm_raw()
|
||||
, Iso_fmt = new Pft_fmt_itm_iso_fmt()
|
||||
, Rfc_5322 = new Pft_fmt_itm_rfc_5322()
|
||||
, Timezone_offset = new Pft_fmt_itm_timezone_offset()
|
||||
;
|
||||
public static final Btrie_fast_mgr Regy = Btrie_fast_mgr.cs_()
|
||||
.Add(Byte_ascii.Ltr_Y , Pft_fmt_itm_.Year_len4) // 2012
|
||||
.Add(Byte_ascii.Ltr_y , Pft_fmt_itm_.Year_len2) // 12
|
||||
.Add(Byte_ascii.Ltr_L , Pft_fmt_itm_.Year_isLeap) // 1,0
|
||||
.Add(Byte_ascii.Ltr_o , Pft_fmt_itm_.Year_len4) // 2012: ISO-8601; don't know why it's different vs Ltr_Y
|
||||
.Add(Byte_ascii.Ltr_n , Pft_fmt_itm_.Month_int) // 1
|
||||
.Add(Byte_ascii.Ltr_m , Pft_fmt_itm_.Month_int_len2) // 01
|
||||
.Add(Byte_ascii.Ltr_M , Pft_fmt_itm_.Month_abrv) // Jan
|
||||
.Add(Byte_ascii.Ltr_F , Pft_fmt_itm_.Month_name) // January
|
||||
.Add("xg" , Pft_fmt_itm_.Month_gen) // January
|
||||
.Add(Byte_ascii.Ltr_W , Pft_fmt_itm_.WeekOfYear_int_len2) // 01
|
||||
.Add(Byte_ascii.Ltr_j , Pft_fmt_itm_.Day_int) // 1
|
||||
.Add(Byte_ascii.Ltr_d , Pft_fmt_itm_.Day_int_len2) // 01
|
||||
.Add(Byte_ascii.Ltr_z , Pft_fmt_itm_.DayOfYear_int) // 0
|
||||
.Add(Byte_ascii.Ltr_D , Pft_fmt_itm_.Dow_abrv) // Sun
|
||||
.Add(Byte_ascii.Ltr_l , Pft_fmt_itm_.Dow_name) // Sunday
|
||||
.Add(Byte_ascii.Ltr_N , Pft_fmt_itm_.Dow_base0_int) // 1; Sunday=7
|
||||
.Add(Byte_ascii.Ltr_w , Pft_fmt_itm_.Dow_base1_int) // 1; Sunday=0
|
||||
.Add(Byte_ascii.Ltr_a , Pft_fmt_itm_.AmPm_lower) // am/pm
|
||||
.Add(Byte_ascii.Ltr_A , Pft_fmt_itm_.AmPm_upper) // AM/PM
|
||||
.Add(Byte_ascii.Ltr_g , Pft_fmt_itm_.Hour_base12) // 1; Base12
|
||||
.Add(Byte_ascii.Ltr_h , Pft_fmt_itm_.Hour_base12_len2) // 01; Base12; pad2
|
||||
.Add(Byte_ascii.Ltr_G , Pft_fmt_itm_.Hour_base24) // 13; Base24;
|
||||
.Add(Byte_ascii.Ltr_H , Pft_fmt_itm_.Hour_base24_len2) // 13; Base24; pad2
|
||||
.Add(Byte_ascii.Ltr_i , Pft_fmt_itm_.Minute_int_len2) // 04
|
||||
.Add(Byte_ascii.Ltr_s , Pft_fmt_itm_.Second_int_len2) // 05
|
||||
.Add(Byte_ascii.Ltr_t , Pft_fmt_itm_.DaysInMonth_int) // 31
|
||||
.Add(Byte_ascii.Ltr_U , Pft_fmt_itm_.Timestamp_unix) // 1343865600
|
||||
.Add(Byte_ascii.Ltr_Z , Pft_fmt_itm_.Timezone_offset) // timezone offset in seconds
|
||||
.Add(Byte_ascii.Ltr_c , Pft_fmt_itm_.Iso_fmt) // 2012-01-02T03:04:05+00:00
|
||||
.Add(Byte_ascii.Ltr_r , Pft_fmt_itm_.Rfc_5322) // Mon 02 Jan 2012 08:04:05 +0000
|
||||
.Add("xr" , Pft_fmt_itm_.Roman) // MCXI
|
||||
.Add("xkY" , Pft_fmt_itm_.Thai) // Year += 543
|
||||
.Add("xoY" , Pft_fmt_itm_.Minguo) // Year -= 1911
|
||||
.Add("xn" , Pft_fmt_itm_.Raw) // NOTE: really does nothing; REF.MW: Language.php|sprintfdate does $s .= $num; DATE:2013-12-31
|
||||
.Add("xN" , Pft_fmt_itm_.Raw)
|
||||
.Add("xjj" , Pft_fmt_itm_.Hebrew_day_num)
|
||||
.Add("xjn" , Pft_fmt_itm_.Hebrew_month_num)
|
||||
.Add("xjt" , Pft_fmt_itm_.Hebrew_month_days_count)
|
||||
.Add("xjF" , Pft_fmt_itm_.Hebrew_month_name_full)
|
||||
.Add("xjx" , Pft_fmt_itm_.Hebrew_month_name_gen)
|
||||
.Add("xjY" , Pft_fmt_itm_.Hebrew_year_num)
|
||||
.Add("xh" , Pft_fmt_itm_.Hebrew_numeral)
|
||||
// TODO: foreign; space; "
|
||||
;
|
||||
public static Pft_fmt_itm[] Parse(Xop_ctx ctx, byte[] fmt) {
|
||||
Btrie_fast_mgr trie = Pft_fmt_itm_.Regy;
|
||||
int i = 0, fmt_len = fmt.length;
|
||||
fmt_itms.Clear(); int raw_bgn = String_.Pos_neg1; byte raw_byt = Byte_.Zero;
|
||||
while (i < fmt_len) {
|
||||
byte b = fmt[i];
|
||||
Object o = trie.Match_bgn_w_byte(b, fmt, i, fmt_len);
|
||||
if (o != null) {
|
||||
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
|
||||
fmt_itms.Add((Pft_fmt_itm)o);
|
||||
i = trie.Match_pos();
|
||||
}
|
||||
else {
|
||||
switch (b) {
|
||||
case Byte_ascii.Backslash:
|
||||
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
|
||||
++i; // peek next char
|
||||
if (i == fmt_len) // trailing backslash; add one; EX: "b\" -> "b\" not "b"
|
||||
fmt_itms.Add(new Pft_fmt_itm_raw_byt(Byte_ascii.Backslash));
|
||||
else
|
||||
fmt_itms.Add(new Pft_fmt_itm_raw_byt(fmt[i]));
|
||||
++i;
|
||||
break;
|
||||
case Byte_ascii.Quote:
|
||||
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(i - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(raw_byt) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i)); raw_bgn = String_.Pos_neg1;}
|
||||
++i; // skip quote_bgn
|
||||
raw_bgn = i;
|
||||
while (i < fmt_len) {
|
||||
b = fmt[i];
|
||||
if (b == Byte_ascii.Quote) {
|
||||
break;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
fmt_itms.Add(i - raw_bgn == 0 ? new Pft_fmt_itm_raw_byt(Byte_ascii.Quote) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, i));
|
||||
raw_bgn = String_.Pos_neg1;
|
||||
++i; // skip quote_end
|
||||
break;
|
||||
default:
|
||||
if (raw_bgn == String_.Pos_neg1) {raw_bgn = i; raw_byt = b;}
|
||||
i += gplx.intl.Utf8_.Len_of_char_by_1st_byte(b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (raw_bgn != String_.Pos_neg1) {fmt_itms.Add(fmt_len - raw_bgn == 1 ? new Pft_fmt_itm_raw_byt(fmt[fmt_len - 1]) : (Pft_fmt_itm)new Pft_fmt_itm_raw_ary(fmt, raw_bgn, fmt_len)); raw_bgn = String_.Pos_neg1;}
|
||||
return (Pft_fmt_itm[])fmt_itms.To_ary(Pft_fmt_itm.class);
|
||||
} private static List_adp fmt_itms = List_adp_.new_();
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
class Pft_fmt_itm_roman implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_roman;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int nxt_idx = bldr.Idx_cur() + 1;
|
||||
Pft_fmt_itm[] ary = bldr.Fmt_itms();
|
||||
if (nxt_idx < ary.length) {
|
||||
Pft_fmt_itm itm = (Pft_fmt_itm)ary[nxt_idx];
|
||||
if (itm.TypeId() == Pft_fmt_itm_.Tid_seg_int) {
|
||||
Pft_fmt_itm_seg_int nxt_int = (Pft_fmt_itm_seg_int)ary[nxt_idx]; // FUTURE: should check tkn type
|
||||
int v = date.Segment(nxt_int.SegIdx());
|
||||
Pfxtp_roman.ToRoman(v, bfr);
|
||||
bldr.Idx_nxt_(nxt_idx + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
bfr.Add_str_a7("xf");
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_thai implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_thai;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add_int_variable(date.Year() + 543);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_minguo implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_minguo;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add_int_variable(date.Year() - 1911);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_hebrew_year_num implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_hebrew_year_num;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int[] hebrew_date = Pft_fmt_itm_hebrew_.Calc_hebrew_date(date);
|
||||
bfr.Add_int_variable(hebrew_date[Pft_fmt_itm_hebrew_.Rslt_year_num]);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_hebrew_month_num implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_hebrew_month_num;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int[] hebrew_date = Pft_fmt_itm_hebrew_.Calc_hebrew_date(date);
|
||||
bfr.Add_int_variable(hebrew_date[Pft_fmt_itm_hebrew_.Rslt_month_num]);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_hebrew_day_num implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_hebrew_day_num;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int[] hebrew_date = Pft_fmt_itm_hebrew_.Calc_hebrew_date(date);
|
||||
bfr.Add_int_variable(hebrew_date[Pft_fmt_itm_hebrew_.Rslt_day_num]);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_hebrew_month_days_count implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_hebrew_month_days_count;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int[] hebrew_date = Pft_fmt_itm_hebrew_.Calc_hebrew_date(date);
|
||||
bfr.Add_int_variable(hebrew_date[Pft_fmt_itm_hebrew_.Rslt_month_days_count]);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_hebrew_month_name_full implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_hebrew_month_name_full;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add(Pft_fmt_itm_hebrew_.Get_hebrew_month_name_full(wiki, date));
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_hebrew_month_name_gen implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_hebrew_month_name_gen;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add(Pft_fmt_itm_hebrew_.Get_hebrew_month_name_gen(wiki, date));
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_hebrew_numeral implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_hebrew_numeral;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add_str(Pft_fmt_itm_hebrew_.Calc_hebrew_numeral(date.Year()));
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_hebrew_ {
|
||||
public static int Calc_hebrew_year_num_start(int year) {
|
||||
int year_minus_1 = year - 1;
|
||||
int a = (12 * year_minus_1 + 17) % 19;
|
||||
int b = year_minus_1 % 4;
|
||||
double m = 32.044093161144d + 1.5542417966212d * a + b / 4.0 - 0.0031777940220923d * year_minus_1;
|
||||
if (m < 0)
|
||||
m--;
|
||||
int mar = (int)m;
|
||||
if (m < 0)
|
||||
m++;
|
||||
m -= mar;
|
||||
int c = (mar + 3 * year_minus_1 + 5 * b + 5) % 7;
|
||||
if (c == 0 && a > 11 && m >= 0.89772376543210d)
|
||||
mar++;
|
||||
else if (c == 1 && a > 6 && m >= 0.63287037037037d)
|
||||
mar += 2;
|
||||
else if (c == 2 || c == 4 || c == 6)
|
||||
mar++;
|
||||
double year_minus_3761 = year - 3761;
|
||||
mar += (int)(year_minus_3761 / 100 ) - (int)(year_minus_3761 / 400) - 24;
|
||||
return mar;
|
||||
}
|
||||
private static final int[] Hebrew_date_rslt = new int[4];
|
||||
public static int[] Calc_hebrew_date(DateAdp date) {
|
||||
synchronized (Hebrew_date_rslt) {
|
||||
Calc_hebrew_date(Hebrew_date_rslt, date.Year(), date.Month(), date.Day());
|
||||
return Hebrew_date_rslt;
|
||||
}
|
||||
}
|
||||
public static boolean Calc_hebrew_date(int[] rv, int year, int month, int day) { // REF.MW:Language.php|tsToHebrew
|
||||
// Calculate Hebrew year
|
||||
int hebrewYear = year + 3760;
|
||||
|
||||
// Month number when September = 1, August = 12
|
||||
month += 4;
|
||||
if (month > 12) {
|
||||
// Next year
|
||||
month -= 12;
|
||||
year++;
|
||||
hebrewYear++;
|
||||
}
|
||||
|
||||
// Calculate day of year from 1 September
|
||||
int dayOfYear = day;
|
||||
for (int i = 1; i < month; i++) {
|
||||
if (i == 6) {
|
||||
// February
|
||||
dayOfYear += 28;
|
||||
// Check if the year is leap
|
||||
if (year % 400 == 0 || (year % 4 == 0 && year % 100 > 0)) {
|
||||
dayOfYear++;
|
||||
}
|
||||
} else if (i == 8 || i == 10 || i == 1 || i == 3) {
|
||||
dayOfYear += 30;
|
||||
} else {
|
||||
dayOfYear += 31;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the start of the Hebrew year
|
||||
int start = Calc_hebrew_year_num_start(hebrewYear);
|
||||
|
||||
// Calculate next year's start
|
||||
int nextStart = 0;
|
||||
if (dayOfYear <= start) {
|
||||
// Day is before the start of the year - it is the previous year
|
||||
// Next year's start
|
||||
nextStart = start;
|
||||
// Previous year
|
||||
year--;
|
||||
hebrewYear--;
|
||||
// Add days since previous year's 1 September
|
||||
dayOfYear += 365;
|
||||
if ((year % 400 == 0) || (year % 100 != 0 && year % 4 == 0)) {
|
||||
// Leap year
|
||||
dayOfYear++;
|
||||
}
|
||||
// Start of the new (previous) year
|
||||
start = Calc_hebrew_year_num_start(hebrewYear);
|
||||
} else {
|
||||
// Next year's start
|
||||
nextStart = Calc_hebrew_year_num_start(hebrewYear + 1);
|
||||
}
|
||||
|
||||
// Calculate Hebrew day of year
|
||||
int hebrewDayOfYear = dayOfYear - start;
|
||||
|
||||
// Difference between year's days
|
||||
int diff = nextStart - start;
|
||||
// Add 12 (or 13 for leap years) days to ignore the difference between
|
||||
// Hebrew and Gregorian year (353 at least vs. 365/6) - now the
|
||||
// difference is only about the year type
|
||||
if ((year % 400 == 0) || (year % 100 != 0 && year % 4 == 0)) {
|
||||
diff += 13;
|
||||
} else {
|
||||
diff += 12;
|
||||
}
|
||||
|
||||
// Check the year pattern, and is leap year
|
||||
// 0 means an incomplete year, 1 means a regular year, 2 means a complete year
|
||||
// This is mod 30, to work on both leap years (which add 30 days of Adar I)
|
||||
// and non-leap years
|
||||
int yearPattern = diff % 30;
|
||||
// Check if leap year
|
||||
boolean isLeap = diff >= 30;
|
||||
|
||||
// Calculate day in the month from number of day in the Hebrew year
|
||||
// Don't check Adar - if the day is not in Adar, we will stop before;
|
||||
// if it is in Adar, we will use it to check if it is Adar I or Adar II
|
||||
int hebrewDay = hebrewDayOfYear;
|
||||
int hebrewMonth = 1;
|
||||
int days = 0;
|
||||
|
||||
while (hebrewMonth <= 12) {
|
||||
// Calculate days in this month
|
||||
if (isLeap && hebrewMonth == 6) {
|
||||
// Adar in a leap year
|
||||
if (isLeap) {
|
||||
// Leap year - has Adar I, with 30 days, and Adar II, with 29 days
|
||||
days = 30;
|
||||
if (hebrewDay <= days) {
|
||||
// Day in Adar I
|
||||
hebrewMonth = 13;
|
||||
} else {
|
||||
// Subtract the days of Adar I
|
||||
hebrewDay -= days;
|
||||
// Try Adar II
|
||||
days = 29;
|
||||
if (hebrewDay <= days) {
|
||||
// Day in Adar II
|
||||
hebrewMonth = 14;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (hebrewMonth == 2 && yearPattern == 2) {
|
||||
// Cheshvan in a complete year (otherwise as the rule below)
|
||||
days = 30;
|
||||
} else if (hebrewMonth == 3 && yearPattern == 0) {
|
||||
// Kislev in an incomplete year (otherwise as the rule below)
|
||||
days = 29;
|
||||
} else {
|
||||
// Odd months have 30 days, even have 29
|
||||
days = 30 - (hebrewMonth - 1) % 2;
|
||||
}
|
||||
if (hebrewDay <= days) {
|
||||
// In the current month
|
||||
break;
|
||||
} else {
|
||||
// Subtract the days of the current month
|
||||
hebrewDay -= days;
|
||||
// Try in the next month
|
||||
hebrewMonth++;
|
||||
}
|
||||
}
|
||||
rv[0] = hebrewYear;
|
||||
rv[1] = hebrewMonth;
|
||||
rv[2] = hebrewDay;
|
||||
rv[3] = days;
|
||||
return true;
|
||||
}
|
||||
public static byte[] Get_hebrew_month_name_full(Xowe_wiki wiki, DateAdp date) {return Get_hebrew_month_name(wiki, date, Month_name_full_ary);}
|
||||
public static byte[] Get_hebrew_month_name_gen(Xowe_wiki wiki, DateAdp date) {return Get_hebrew_month_name(wiki, date, Month_name_gen_ary);}
|
||||
private static byte[] Get_hebrew_month_name(Xowe_wiki wiki, DateAdp date, byte[][] name_ary) {
|
||||
int[] hebrew_date = Pft_fmt_itm_hebrew_.Calc_hebrew_date(date);
|
||||
int hebrew_month = hebrew_date[Pft_fmt_itm_hebrew_.Rslt_month_num] - List_adp_.Base1;
|
||||
byte[] msg_key = name_ary[hebrew_month];
|
||||
return wiki.Msg_mgr().Val_by_key_obj(msg_key);
|
||||
}
|
||||
private static final byte[][] Month_name_full_ary = new byte[][]
|
||||
{ Bry_.new_a7("hebrew-calendar-m1"), Bry_.new_a7("hebrew-calendar-m2"), Bry_.new_a7("hebrew-calendar-m3")
|
||||
, Bry_.new_a7("hebrew-calendar-m4"), Bry_.new_a7("hebrew-calendar-m5"), Bry_.new_a7("hebrew-calendar-m6")
|
||||
, Bry_.new_a7("hebrew-calendar-m7"), Bry_.new_a7("hebrew-calendar-m8"), Bry_.new_a7("hebrew-calendar-m9")
|
||||
, Bry_.new_a7("hebrew-calendar-m10"), Bry_.new_a7("hebrew-calendar-m11"), Bry_.new_a7("hebrew-calendar-m12")
|
||||
, Bry_.new_a7("hebrew-calendar-m6a"), Bry_.new_a7("hebrew-calendar-m6b")
|
||||
};
|
||||
private static final byte[][] Month_name_gen_ary = new byte[][]
|
||||
{ Bry_.new_a7("hebrew-calendar-m1-gen"), Bry_.new_a7("hebrew-calendar-m2-gen"), Bry_.new_a7("hebrew-calendar-m3-gen")
|
||||
, Bry_.new_a7("hebrew-calendar-m4-gen"), Bry_.new_a7("hebrew-calendar-m5-gen"), Bry_.new_a7("hebrew-calendar-m6-gen")
|
||||
, Bry_.new_a7("hebrew-calendar-m7-gen"), Bry_.new_a7("hebrew-calendar-m8-gen"), Bry_.new_a7("hebrew-calendar-m9-gen")
|
||||
, Bry_.new_a7("hebrew-calendar-m10-gen"), Bry_.new_a7("hebrew-calendar-m11-gen"), Bry_.new_a7("hebrew-calendar-m12-gen")
|
||||
, Bry_.new_a7("hebrew-calendar-m6a-gen"), Bry_.new_a7("hebrew-calendar-m6b-gen")
|
||||
};
|
||||
public static final int
|
||||
Rslt_year_num = 0
|
||||
, Rslt_month_num = 1
|
||||
, Rslt_day_num = 2
|
||||
, Rslt_month_days_count = 3
|
||||
;
|
||||
|
||||
private static final String[][] Numeral_tbls = new String[][]
|
||||
{ new String[] {"", "א", "ב", "ג", "ד", "ה", "ו", "ז", "ח", "ט", "י"}
|
||||
, new String[] {"", "י", "כ", "ל", "מ", "נ", "ס", "ע", "פ", "צ", "ק"}
|
||||
, new String[] {"", "ק", "ר", "ש", "ת", "תק", "תר", "תש", "תת", "תתק", "תתר"}
|
||||
, new String[] {"", "א", "ב", "ג", "ד", "ה", "ו", "ז", "ח", "ט", "י"}
|
||||
};
|
||||
public static String Calc_hebrew_numeral(int num) {
|
||||
if (num > 9999 || num <= 0)
|
||||
return Int_.Xto_str(num);
|
||||
|
||||
String tmp = "";
|
||||
int pow10 = 1000;
|
||||
for (int i = 3; i >= 0; pow10 /= 10, i--) {
|
||||
if (num >= pow10) {
|
||||
if (num == 15 || num == 16) {
|
||||
tmp += Numeral_tbls[0][9] + Numeral_tbls[0][num - 9];
|
||||
num = 0;
|
||||
} else {
|
||||
tmp += Numeral_tbls[i][(int)(num / pow10)];
|
||||
if (pow10 == 1000)
|
||||
tmp += "'";
|
||||
}
|
||||
}
|
||||
num = num % pow10;
|
||||
}
|
||||
String rv = "";
|
||||
int tmp_len = String_.Len(tmp);
|
||||
if (tmp_len == 2) {
|
||||
rv = tmp + "'";
|
||||
}
|
||||
else {
|
||||
rv = String_.Mid(tmp, 0, tmp_len - 1) + "\"";
|
||||
rv += String_.Mid(tmp, tmp_len - 1);
|
||||
}
|
||||
int rv_len = String_.Len(rv);
|
||||
String start = String_.Mid(rv, 0, rv_len - 1);
|
||||
String end = String_.Mid(rv, rv_len - 1);
|
||||
if (String_.Eq(end, "כ"))
|
||||
rv = start + "ך";
|
||||
else if (String_.Eq(end, "מ"))
|
||||
rv = start + "ם";
|
||||
else if (String_.Eq(end, "נ"))
|
||||
rv = start + "ן";
|
||||
else if (String_.Eq(end, "פ"))
|
||||
rv = start + "ף";
|
||||
else if (String_.Eq(end, "צ"))
|
||||
rv = start + "ץ";
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
class Pft_fmt_itm_seg_int implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_seg_int(int segIdx, int len, boolean fixed_len) {this.segIdx = segIdx; this.fixed_len = fixed_len; this.len = len;} private int segIdx, len; boolean fixed_len;
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_seg_int;}
|
||||
public int SegIdx() {return segIdx;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int val = date.Segment(segIdx);
|
||||
if (fixed_len) bfr.Add_int_fixed(val, len);
|
||||
else bfr.Add_int_variable(val);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_raw implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_raw;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
// TODO: should flag .Raw() on bldr to skip transliterating numerals in foreign languages; DATE:2013-12-31
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_seg_str implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_seg_str(int segIdx, int type) {this.segIdx = segIdx; this.type = type;} private int segIdx, type;
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_seg_str;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
DateAdpTranslator_xapp.Translate(wiki, lang, type, date.Segment(segIdx), bfr);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_year_isLeap implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_year_isLeap;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_int_fixed(DateAdp_.IsLeapYear(date.Year()) ? 1 : 0, 1);}
|
||||
}
|
||||
class Pft_fmt_itm_hour_base12 implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_hour_base12;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int val = date.Hour();
|
||||
switch (val) {
|
||||
case 0: val = 12; break;
|
||||
case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: val -= 12; break;
|
||||
default: break;
|
||||
}
|
||||
if (fixed_len) bfr.Add_int_fixed(val, 2);
|
||||
else bfr.Add_int_variable(val);
|
||||
}
|
||||
public Pft_fmt_itm_hour_base12(boolean fixed_len) {this.fixed_len = fixed_len;} private boolean fixed_len;
|
||||
}
|
||||
class Pft_fmt_itm_timestamp_unix implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_timestamp_unix;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_long_variable(date.Timestamp_unix());}
|
||||
}
|
||||
class Pft_fmt_itm_raw_ary implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_raw_ary;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_mid(src, bgn, end);}
|
||||
public Pft_fmt_itm_raw_ary(byte[] src, int bgn, int end) {this.src = src; this.bgn = bgn; this.end = end;} private byte[] src; int bgn; int end;
|
||||
}
|
||||
class Pft_fmt_itm_raw_byt implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_raw_byt;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_byte(b);}
|
||||
public Pft_fmt_itm_raw_byt(byte b) {this.b = b;} private byte b;
|
||||
}
|
||||
class Pft_fmt_itm_daysInMonth implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_daysInMonth;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_int_variable(DateAdp_.DaysInMonth(date));}
|
||||
}
|
||||
class Pft_fmt_itm_dayOfYear implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_dayOfYear;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {bfr.Add_int_variable(date.DayOfYear() - Int_.Base1);} // php is base1; .net/java is base0
|
||||
}
|
||||
class Pft_fmt_itm_am_pm implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_AmPm;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
boolean am = date.Hour() < 13;
|
||||
byte[] val = null;
|
||||
if ( am && lower) val = Ary_am_lower;
|
||||
else if ( am && !lower) val = Ary_am_upper;
|
||||
else if (!am && lower) val = Ary_pm_lower;
|
||||
else if (!am && !lower) val = Ary_pm_upper;
|
||||
bfr.Add(val);
|
||||
} static final byte[] Ary_am_upper = Bry_.new_a7("AM"), Ary_pm_upper = Bry_.new_a7("PM"), Ary_am_lower = Bry_.new_a7("am"), Ary_pm_lower = Bry_.new_a7("pm");
|
||||
public Pft_fmt_itm_am_pm(boolean lower) {this.lower = lower;} private boolean lower;
|
||||
}
|
||||
class Pft_fmt_itm_dow_base0 implements Pft_fmt_itm {
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_dow_base0;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
int dow = date.DayOfWeek();
|
||||
if (dow == 0) dow = 7;
|
||||
bfr.Add_int_fixed(dow, 1);
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_iso_fmt implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_iso_fmt() {}
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_iso_fmt;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add_str(date.XtoStr_fmt("yyyy-MM-dd"));
|
||||
bfr.Add_byte(Byte_ascii.Ltr_T);
|
||||
bfr.Add_str(date.XtoStr_fmt("HH:mm:ss"));
|
||||
bfr.Add_str(date.XtoStr_tz());
|
||||
}
|
||||
}
|
||||
class Pft_fmt_itm_rfc_5322 implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_rfc_5322() {}
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_rfc_5322;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {// Mon, 02 Jan 2012 10:15:01 +0000
|
||||
int dow = date.DayOfWeek();
|
||||
DateAdpTranslator_xapp.Translate(wiki, lang, DateAdp_.SegIdx_dayOfWeek, dow, bfr);
|
||||
bfr.Add_byte(Byte_ascii.Comma).Add_byte(Byte_ascii.Space);
|
||||
bfr.Add_str(date.XtoStr_fmt("dd MMM yyyy HH:mm:ss")); // NOTE: always UTC time
|
||||
bfr.Add(CONST_timezone); // NOTE: always UTC time zone
|
||||
} static final byte[] CONST_timezone = Bry_.new_a7(" +0000");
|
||||
}
|
||||
class Pft_fmt_itm_timezone_offset implements Pft_fmt_itm {
|
||||
public Pft_fmt_itm_timezone_offset() {}
|
||||
public int TypeId() {return Pft_fmt_itm_.Tid_timezone_offset;}
|
||||
public void Fmt(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_func_formatdate_bldr bldr) {
|
||||
bfr.Add_int_variable(date.Timezone_offset());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pft_func_date_int extends Pf_func_base {
|
||||
public Pft_func_date_int(int id, int date_tid) {this.id = id; this.date_tid = date_tid;} private int date_tid;
|
||||
@Override public int Id() {return id;} private int id;
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pft_func_date_int(id, date_tid).Name_(name);}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
DateAdp date = DateAdp_.MinValue;
|
||||
Xowe_wiki wiki = ctx.Wiki(); Xol_lang lang = ctx.Lang();
|
||||
switch (date_tid) {
|
||||
case Date_tid_lcl: date = DateAdp_.Now(); break;
|
||||
case Date_tid_utc: date = DateAdp_.Now().XtoUtc(); break;
|
||||
case Date_tid_rev: date = ctx.Cur_page().Revision_data().Modified_on(); break;
|
||||
default: throw Exc_.new_unhandled(date_tid);
|
||||
}
|
||||
switch (id) {
|
||||
case Xol_kwd_grp_.Id_utc_year:
|
||||
case Xol_kwd_grp_.Id_lcl_year:
|
||||
case Xol_kwd_grp_.Id_rev_year:
|
||||
Pft_func_formatdate.Date_bldr().Format(bfr, wiki, lang, date, Pft_fmt_itm_.Year_len4);
|
||||
break;
|
||||
case Xol_kwd_grp_.Id_utc_month_int_len2:
|
||||
case Xol_kwd_grp_.Id_lcl_month_int_len2:
|
||||
case Xol_kwd_grp_.Id_rev_month_int_len2:
|
||||
Pft_func_formatdate.Date_bldr().Format(bfr, wiki, lang, date, Pft_fmt_itm_.Month_int_len2);
|
||||
break;
|
||||
case Xol_kwd_grp_.Id_utc_month_int:
|
||||
case Xol_kwd_grp_.Id_lcl_month_int:
|
||||
case Xol_kwd_grp_.Id_rev_month_int:
|
||||
Pft_func_formatdate.Date_bldr().Format(bfr, wiki, lang, date, Pft_fmt_itm_.Month_int);
|
||||
break;
|
||||
case Xol_kwd_grp_.Id_utc_day_int_len2:
|
||||
case Xol_kwd_grp_.Id_lcl_day_int_len2:
|
||||
case Xol_kwd_grp_.Id_rev_day_int_len2:
|
||||
Pft_func_formatdate.Date_bldr().Format(bfr, wiki, lang, date, Pft_fmt_itm_.Day_int_len2);
|
||||
break;
|
||||
case Xol_kwd_grp_.Id_utc_day_int:
|
||||
case Xol_kwd_grp_.Id_lcl_day_int:
|
||||
case Xol_kwd_grp_.Id_rev_day_int:
|
||||
Pft_func_formatdate.Date_bldr().Format(bfr, wiki, lang, date, Pft_fmt_itm_.Day_int);
|
||||
break;
|
||||
case Xol_kwd_grp_.Id_lcl_hour:
|
||||
case Xol_kwd_grp_.Id_utc_hour:
|
||||
Pft_func_formatdate.Date_bldr().Format(bfr, wiki, lang, date, Pft_fmt_itm_.Hour_base24_len2);
|
||||
break;
|
||||
case Xol_kwd_grp_.Id_lcl_dow:
|
||||
case Xol_kwd_grp_.Id_utc_dow:
|
||||
Pft_func_formatdate.Date_bldr().Format(bfr, wiki, lang, date, Pft_fmt_itm_.Dow_base1_int);
|
||||
break;
|
||||
case Xol_kwd_grp_.Id_lcl_week:
|
||||
case Xol_kwd_grp_.Id_utc_week:
|
||||
Pft_func_formatdate.Date_bldr().Format(bfr, wiki, lang, date, Pft_fmt_itm_.WeekOfYear_int);
|
||||
break;
|
||||
case Xol_kwd_grp_.Id_lcl_time:
|
||||
case Xol_kwd_grp_.Id_utc_time: // 17:29
|
||||
bfr.Add_int_fixed(date.Hour(), 2).Add_byte(Byte_ascii.Colon).Add_int_fixed(date.Minute(), 2);
|
||||
break;
|
||||
case Xol_kwd_grp_.Id_lcl_timestamp:
|
||||
case Xol_kwd_grp_.Id_utc_timestamp:
|
||||
case Xol_kwd_grp_.Id_rev_timestamp: // 20120123172956
|
||||
bfr .Add_int_fixed(date.Year() , 4)
|
||||
.Add_int_fixed(date.Month() , 2)
|
||||
.Add_int_fixed(date.Day() , 2)
|
||||
.Add_int_fixed(date.Hour() , 2)
|
||||
.Add_int_fixed(date.Minute(), 2)
|
||||
.Add_int_fixed(date.Second(), 2);
|
||||
break;
|
||||
default: throw Exc_.new_unhandled(id);
|
||||
}
|
||||
}
|
||||
public static final int Date_tid_utc = 0, Date_tid_lcl = 1, Date_tid_rev = 2;
|
||||
public static final Pft_func_date_int
|
||||
Utc = new Pft_func_date_int(-1, Date_tid_utc)
|
||||
, Lcl = new Pft_func_date_int(-1, Date_tid_lcl)
|
||||
, Rev = new Pft_func_date_int(-1, Date_tid_rev);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pft_func_date_lcl_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void setup() {fxt.Reset(); Tfds.Now_set(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));}
|
||||
@After public void teardown() {Tfds.Now_enabled_n_();}
|
||||
@Test public void Lcl_year() {fxt.Test_parse_tmpl_str_test("{{LOCALYEAR}}" , "{{test}}", "2012");}
|
||||
@Test public void Lcl_month_int() {fxt.Test_parse_tmpl_str_test("{{LOCALMONTH1}}" , "{{test}}", "1");}
|
||||
@Test public void Lcl_month_int_len2() {fxt.Test_parse_tmpl_str_test("{{LOCALMONTH}}" , "{{test}}", "01");}
|
||||
@Test public void Lcl_day_int() {fxt.Test_parse_tmpl_str_test("{{LOCALDAY}}" , "{{test}}", "2");}
|
||||
@Test public void Lcl_day_int_len2() {fxt.Test_parse_tmpl_str_test("{{LOCALDAY2}}" , "{{test}}", "02");}
|
||||
@Test public void Lcl_day_hour_len2() {fxt.Test_parse_tmpl_str_test("{{LOCALHOUR}}" , "{{test}}", "03");}
|
||||
@Test public void Lcl_dow_int() {fxt.Test_parse_tmpl_str_test("{{LOCALDOW}}" , "{{test}}", "1");}
|
||||
@Test public void Lcl_week_int() {fxt.Test_parse_tmpl_str_test("{{LOCALWEEK}}" , "{{test}}", "1");}
|
||||
@Test public void Lcl_month_name() {fxt.Test_parse_tmpl_str_test("{{LOCALMONTHNAME}}" , "{{test}}", "January");}
|
||||
@Test public void Lcl_month_gen() {fxt.Test_parse_tmpl_str_test("{{LOCALMONTHNAMEGEN}}" , "{{test}}", "January");}
|
||||
@Test public void Lcl_day_name() {fxt.Test_parse_tmpl_str_test("{{LOCALDAYNAME}}" , "{{test}}", "Monday");}
|
||||
@Test public void Lcl_time() {fxt.Test_parse_tmpl_str_test("{{LOCALTIME}}" , "{{test}}", "03:04");}
|
||||
@Test public void Lcl_timestamp() {fxt.Test_parse_tmpl_str_test("{{LOCALTIMESTAMP}}" , "{{test}}", "20120102030405");}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pft_func_date_name extends Pf_func_base {
|
||||
public Pft_func_date_name(int id, int date_tid, int seg_idx, int base_idx) {this.id = id; this.date_tid = date_tid; this.seg_idx = seg_idx; this.base_idx = base_idx;} private int date_tid, seg_idx, base_idx;
|
||||
@Override public int Id() {return id;} private int id;
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pft_func_date_name(id, date_tid, seg_idx, base_idx).Name_(name);}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
DateAdp date = DateAdp_.MinValue;
|
||||
switch (date_tid) {
|
||||
case Pft_func_date_int.Date_tid_lcl: date = DateAdp_.Now(); break;
|
||||
case Pft_func_date_int.Date_tid_utc: date = DateAdp_.Now().XtoUtc(); break;
|
||||
case Pft_func_date_int.Date_tid_rev: date = ctx.Cur_page().Revision_data().Modified_on(); break;
|
||||
default: throw Exc_.new_unhandled(date_tid);
|
||||
}
|
||||
byte[] val = ctx.Wiki().Msg_mgr().Val_by_id(base_idx + date.Segment(seg_idx));
|
||||
bfr.Add(val);
|
||||
// translator.Translate(base_idx, date.Segment(seg_idx), bfr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pft_func_date_rev_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void setup() {fxt.Reset(); fxt.Page().Revision_data().Modified_on_(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));}
|
||||
@After public void teardown() {}
|
||||
@Test public void Rev_year() {fxt.Test_parse_tmpl_str_test("{{REVISIONYEAR}}" , "{{test}}", "2012");}
|
||||
@Test public void Rev_month_int() {fxt.Test_parse_tmpl_str_test("{{REVISIONMONTH1}}" , "{{test}}", "1");}
|
||||
@Test public void Rev_month_int_len2() {fxt.Test_parse_tmpl_str_test("{{REVISIONMONTH}}" , "{{test}}", "01");}
|
||||
@Test public void Rev_day_int() {fxt.Test_parse_tmpl_str_test("{{REVISIONDAY}}" , "{{test}}", "2");}
|
||||
@Test public void Rev_day_int_len2() {fxt.Test_parse_tmpl_str_test("{{REVISIONDAY2}}" , "{{test}}", "02");}
|
||||
@Test public void Rev_timestamp() {fxt.Test_parse_tmpl_str_test("{{REVISIONTIMESTAMP}}" , "{{test}}", "20120102030405");}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pft_func_date_utc_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void setup() {fxt.Reset(); Tfds.Now_set(DateAdp_.new_(2011, 12, 31, 22, 4, 5, 6));} // ENV:Assumes Eastern Standard Time (-5)
|
||||
@After public void teardown() {Tfds.Now_enabled_n_();}
|
||||
@Test public void Utc_year() {fxt.Test_parse_tmpl_str_test("{{CURRENTYEAR}}" , "{{test}}", "2012");}
|
||||
@Test public void Utc_month_int() {fxt.Test_parse_tmpl_str_test("{{CURRENTMONTH1}}" , "{{test}}", "1");}
|
||||
@Test public void Utc_month_int_len2() {fxt.Test_parse_tmpl_str_test("{{CURRENTMONTH}}" , "{{test}}", "01");}
|
||||
@Test public void Utc_day_int() {fxt.Test_parse_tmpl_str_test("{{CURRENTDAY}}" , "{{test}}", "1");}
|
||||
@Test public void Utc_day_int_len2() {fxt.Test_parse_tmpl_str_test("{{CURRENTDAY2}}" , "{{test}}", "01");}
|
||||
@Test public void Utc_day_hour_len2() {fxt.Test_parse_tmpl_str_test("{{CURRENTHOUR}}" , "{{test}}", "03");}
|
||||
@Test public void Utc_dow_int() {fxt.Test_parse_tmpl_str_test("{{CURRENTDOW}}" , "{{test}}", "0");}
|
||||
@Test public void Utc_week_int() {fxt.Test_parse_tmpl_str_test("{{CURRENTWEEK}}" , "{{test}}", "1");}
|
||||
@Test public void Utc_month_abrv() {fxt.Test_parse_tmpl_str_test("{{CURRENTMONTHABBREV}}" , "{{test}}", "Jan");}
|
||||
@Test public void Utc_month_name() {fxt.Test_parse_tmpl_str_test("{{CURRENTMONTHNAME}}" , "{{test}}", "January");}
|
||||
@Test public void Utc_month_gen() {fxt.Test_parse_tmpl_str_test("{{CURRENTMONTHNAMEGEN}}" , "{{test}}", "January");}
|
||||
@Test public void Utc_day_name() {fxt.Test_parse_tmpl_str_test("{{CURRENTDAYNAME}}" , "{{test}}", "Sunday");}
|
||||
@Test public void Utc_time() {fxt.Test_parse_tmpl_str_test("{{CURRENTTIME}}" , "{{test}}", "03:04");}
|
||||
@Test public void Utc_timestamp() {fxt.Test_parse_tmpl_str_test("{{CURRENTTIMESTAMP}}" , "{{test}}", "20120101030405");}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Pft_func_formatdate extends Pf_func_base {
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_str_formatdate;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pft_func_formatdate().Name_(name);}
|
||||
@Override public boolean Func_require_colon_arg() {return true;}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {
|
||||
int self_args_len = self.Args_len();
|
||||
byte[] date_bry = Eval_argx(ctx, src, caller, self);
|
||||
byte[] fmt_bry = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0);
|
||||
if (fmt_bry == Bry_.Empty) {bfr.Add(date_bry); return;} // no format given; add self;
|
||||
int fmt_bry_len = fmt_bry.length;
|
||||
Object o = trie.Match_bgn(fmt_bry, 0, fmt_bry_len);
|
||||
if (o == null
|
||||
|| o == Fmt_itms_default) {// NOOP for default?
|
||||
bfr.Add(date_bry);
|
||||
return;
|
||||
}
|
||||
DateAdp date = Pft_func_time.ParseDate(date_bry, false, ctx.App().Utl__bfr_mkr().Get_b512().Mkr_rls());
|
||||
if (date == null) {bfr.Add(date_bry); return;} // date not parseable; return self; DATE:2014-04-13
|
||||
date_bldr.Format(bfr, ctx.Wiki(), ctx.Lang(), date, (Pft_fmt_itm[])o);
|
||||
}
|
||||
public static Pft_func_formatdate_bldr Date_bldr() {return date_bldr;} private static Pft_func_formatdate_bldr date_bldr = new Pft_func_formatdate_bldr();
|
||||
private static final Pft_fmt_itm[] Fmt_itms_default = new Pft_fmt_itm[0];
|
||||
private static final Btrie_fast_mgr trie = Btrie_fast_mgr.cs_()
|
||||
.Add("dmy" , new Pft_fmt_itm[] {Pft_fmt_itm_.Day_int, Pft_fmt_itm_.Byte_space, Pft_fmt_itm_.Month_name, Pft_fmt_itm_.Byte_space, Pft_fmt_itm_.Year_len4})
|
||||
.Add("mdy" , new Pft_fmt_itm[] {Pft_fmt_itm_.Month_name, Pft_fmt_itm_.Byte_space, Pft_fmt_itm_.Day_int, Pft_fmt_itm_.Byte_comma, Pft_fmt_itm_.Byte_space, Pft_fmt_itm_.Year_len4})
|
||||
.Add("ymd" , new Pft_fmt_itm[] {Pft_fmt_itm_.Year_len4, Pft_fmt_itm_.Byte_space, Pft_fmt_itm_.Month_name, Pft_fmt_itm_.Byte_space, Pft_fmt_itm_.Day_int})
|
||||
.Add("ISO 8601" , new Pft_fmt_itm[] {Pft_fmt_itm_.Year_len4, Pft_fmt_itm_.Byte_dash, Pft_fmt_itm_.Month_int_len2, Pft_fmt_itm_.Byte_dash, Pft_fmt_itm_.Day_int_len2})
|
||||
.Add("default" , Fmt_itms_default)
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
public class Pft_func_formatdate_bldr {
|
||||
public int Idx_cur() {return idx_cur;} private int idx_cur;
|
||||
public Pft_func_formatdate_bldr Idx_nxt_(int v) {idx_nxt = v; return this;} private int idx_nxt;
|
||||
public Pft_fmt_itm[] Fmt_itms() {return fmt_itms;} Pft_fmt_itm[] fmt_itms;
|
||||
public void Format(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_fmt_itm fmt_itm) {
|
||||
fmt_itm.Fmt(bfr, wiki, lang, date, this);
|
||||
}
|
||||
public void Format(Bry_bfr bfr, Xowe_wiki wiki, Xol_lang lang, DateAdp date, Pft_fmt_itm[] fmt_itms) {
|
||||
this.fmt_itms = fmt_itms;
|
||||
int len = fmt_itms.length;
|
||||
idx_cur = 0; idx_nxt = -1;
|
||||
Pft_fmt_itm last = null;
|
||||
while (idx_cur < len) {
|
||||
Pft_fmt_itm fmt_itm = fmt_itms[idx_cur];
|
||||
if (fmt_itm.TypeId() == Pft_fmt_itm_.Tid_hebrew_numeral)
|
||||
last = fmt_itm;
|
||||
else {
|
||||
fmt_itm.Fmt(bfr, wiki, lang, date, this);
|
||||
}
|
||||
if (idx_nxt == -1)
|
||||
++idx_cur;
|
||||
else {
|
||||
idx_cur = idx_nxt;
|
||||
idx_nxt = -1;
|
||||
}
|
||||
}
|
||||
if (last != null) {
|
||||
int year_int = bfr.XtoIntAndClear(-1);
|
||||
if (year_int != -1) { // handle no format; EX:{{#time:xh}} DATE:2014-07-20
|
||||
date = DateAdp_.seg_(new int[] {year_int, date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), date.Frac()});
|
||||
last.Fmt(bfr, wiki, lang, date, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pft_func_formatdate_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset();}
|
||||
@Test public void Fmt_dmy() {fxt.Test_parse_tmpl_str_test("{{#formatdate:2012-01-02|dmy}}" , "{{test}}" , "2 January 2012");}
|
||||
@Test public void Fmt_mdy() {fxt.Test_parse_tmpl_str_test("{{#formatdate:2012-01-02|mdy}}" , "{{test}}" , "January 2, 2012");}
|
||||
@Test public void Fmt_ymd() {fxt.Test_parse_tmpl_str_test("{{#formatdate:2012-01-02|ymd}}" , "{{test}}" , "2012 January 2");}
|
||||
@Test public void Fmt_ISO_8601() {fxt.Test_parse_tmpl_str_test("{{#formatdate:2012-01-02|ISO 8601}}" , "{{test}}" , "2012-01-02");}
|
||||
@Test public void Fmt_default() {fxt.Test_parse_tmpl_str_test("{{#formatdate:2012-01-02|default}}" , "{{test}}" , "2012-01-02");} // NOOP?
|
||||
@Test public void Fmt_none() {fxt.Test_parse_tmpl_str_test("{{#formatdate:10 April 2012}}" , "{{test}}" , "10 April 2012");}
|
||||
@Test public void Err_multiple_years() {fxt.Test_parse_tmpl_str_test("{{#formatdate:January 2, 1999, 2000|Y}}" , "{{test}}" , "January 2, 1999, 2000");} // PURPOSE: check that multiple years don't fail
|
||||
@Test public void Unknown() {fxt.Test_parse_tmpl_str_test("{{#formatdate:unknown|dmy}}" , "{{test}}" , "unknown");} // PURPOSE: unknown term should output self, not ""; EX:w:Wikipedia:Wikipedia_Signpost/Newsroom/Opinion_desk/AdminCom; DATE:2014-04-13
|
||||
}
|
||||
/*
|
||||
{{#formatdate:2012-01-02|dmy}}<br/>
|
||||
{{#formatdate:2012-01-02|mdy}}<br/>
|
||||
{{#formatdate:2012-01-02|ymd}}<br/>
|
||||
{{#formatdate:2012-01-02|ISO 8601}}<br/>
|
||||
{{#formatdate:2012-01-02|default}}<br/>
|
||||
*/
|
||||
95
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_func_time.java
Normal file
95
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_func_time.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.xowa.langs.*;
|
||||
public class Pft_func_time extends Pf_func_base {
|
||||
Pft_func_time(boolean utc) {this.utc = utc;} private boolean utc;
|
||||
@Override public int Id() {return Xol_kwd_grp_.Id_xtn_time;}
|
||||
@Override public Pf_func New(int id, byte[] name) {return new Pft_func_time(utc).Name_(name);}
|
||||
@Override public void Func_evaluate(Xop_ctx ctx, byte[] src, Xot_invk caller, Xot_invk self, Bry_bfr bfr) {// REF.MW:ParserFunctions_body.php
|
||||
int self_args_len = self.Args_len();
|
||||
byte[] arg_fmt = Eval_argx(ctx, src, caller, self);
|
||||
Pft_fmt_itm[] fmt_ary = Pft_fmt_itm_.Parse(ctx, arg_fmt);
|
||||
byte[] arg_date = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 0);
|
||||
byte[] arg_lang = Pf_func_.Eval_arg_or_empty(ctx, src, caller, self, self_args_len, 1);
|
||||
Bry_bfr error_bfr = Bry_bfr.new_();
|
||||
DateAdp date = ParseDate(arg_date, utc, error_bfr);
|
||||
if (date == null || error_bfr.Len() > 0)
|
||||
bfr.Add_str_a7("<strong class=\"error\">").Add_bfr_and_clear(error_bfr).Add_str("</strong>");
|
||||
else {
|
||||
Xol_lang lang = ctx.Lang();
|
||||
if (Bry_.Len_gt_0(arg_lang)) {
|
||||
Xol_lang_itm specified_lang_itm = Xol_lang_itm_.Get_by_key(arg_lang);
|
||||
if (specified_lang_itm != null) { // NOTE: if lang_code is bad, then ignore (EX:bad_code)
|
||||
Xol_lang specified_lang = ctx.Wiki().Appe().Lang_mgr().Get_by_key_or_new(arg_lang);
|
||||
lang = specified_lang;
|
||||
}
|
||||
}
|
||||
Pft_func_formatdate.Date_bldr().Format(bfr, ctx.Wiki(), lang, date, fmt_ary);
|
||||
}
|
||||
}
|
||||
public static DateAdp ParseDate(byte[] date, boolean utc, Bry_bfr error_bfr) {
|
||||
if (date == Bry_.Empty) return utc ? DateAdp_.Now().XtoUtc() : DateAdp_.Now();
|
||||
try {
|
||||
DateAdp rv = new Pxd_parser().Parse(date, error_bfr);
|
||||
return rv;
|
||||
}
|
||||
catch (Exception exc) {
|
||||
Exc_.Noop(exc);
|
||||
error_bfr.Add_str_a7("Invalid time");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static final Pft_func_time _Lcl = new Pft_func_time(false), _Utc = new Pft_func_time(true);
|
||||
}
|
||||
class DateAdpTranslator_xapp {
|
||||
public static void Translate(Xowe_wiki wiki, Xol_lang lang, int type, int val, Bry_bfr bb) {
|
||||
lang.Init_by_load_assert();
|
||||
byte[] itm_val = lang.Msg_mgr().Val_by_id(type + val); if (itm_val == null) return;
|
||||
bb.Add(itm_val);
|
||||
}
|
||||
}
|
||||
class Pfxtp_roman {
|
||||
public static void ToRoman(int num, Bry_bfr bfr) {
|
||||
if (num > 3000 || num <= 0) {
|
||||
bfr.Add_int_variable(num);
|
||||
return;
|
||||
}
|
||||
int pow10 = 1000;
|
||||
for (int i = 3; i > -1; i--) {
|
||||
if (num >= pow10) {
|
||||
bfr.Add(Names[i][Math_.Trunc(num / pow10)]);
|
||||
}
|
||||
num %= pow10;
|
||||
pow10 /= 10;
|
||||
}
|
||||
}
|
||||
private static byte[][][] Names = new byte[][][]
|
||||
{ Bry_dim2_new_("", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X")
|
||||
, Bry_dim2_new_("", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "C")
|
||||
, Bry_dim2_new_("", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "M")
|
||||
, Bry_dim2_new_("", "M", "MM", "MMM")
|
||||
};
|
||||
private static byte[][] Bry_dim2_new_(String... names) {
|
||||
int len = names.length;
|
||||
byte[][] rv = new byte[len][];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = Bry_.new_u8(names[i]);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pft_func_time_basic_tst {
|
||||
@Before public void init() {fxt.Reset(); Tfds.Now_set(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));} private Xop_fxt fxt = new Xop_fxt();
|
||||
@After public void term() {Tfds.Now_enabled_n_();}
|
||||
@Test public void Utc_date() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|2012-01-02 03:04:05}}" , "2012-01-02");}
|
||||
@Test public void Utc_time() {fxt.Test_parse_tmpl_str("{{#time:h:i:s A|2012-01-02 03:04:05}}" , "03:04:05 AM");}
|
||||
@Test public void Utc_dayOfYear() {fxt.Test_parse_tmpl_str("{{#time:z|2012-01-01 03:04:05}}" , "0");}
|
||||
@Test public void Utc_escape_basic() {fxt.Test_parse_tmpl_str("{{#time:\\Y Y|2012-01-02 03:04:05}}" , "Y 2012");}
|
||||
@Test public void Utc_escape_double() {fxt.Test_parse_tmpl_str("{{#time:\\\\ Y|2012-01-02 03:04:05}}" , "\\ 2012");}
|
||||
@Test public void Utc_escape_eos() {fxt.Test_parse_tmpl_str("{{#time:b\\|2012-01-02 03:04:05}}" , "b\\");}
|
||||
@Test public void Utc_escape_newLine() {fxt.Test_parse_tmpl_str("{{#time:b\\\nb|2012-01-02 03:04:05}}" , "b\nb");}
|
||||
@Test public void Utc_quote_basic() {fxt.Test_parse_tmpl_str("{{#time:b \"Y m d\" b|2012-01-02 03:04:05}}" , "b Y m d b");}
|
||||
@Test public void Utc_quote_double() {fxt.Test_parse_tmpl_str("{{#time:b \"\" b|2012-01-02 03:04:05}}" , "b \" b");}
|
||||
@Test public void Utc_quote_eos() {fxt.Test_parse_tmpl_str("{{#time:b \"|2012-01-02 03:04:05}}" , "b \"");}
|
||||
@Test public void Utc_ws() {fxt.Test_parse_tmpl_str("{{#time: Y-m-d |2012-01-02 03:04:05}}" , "2012-01-02");}
|
||||
@Test public void Lcl_date() {fxt.Test_parse_tmpl_str("{{#timel:Y-m-d|2012-01-02 03:04:05}}" , "2012-01-02");}
|
||||
@Test public void Utc_dow_abrv() {fxt.Test_parse_tmpl_str("{{#time:D|20120301}}" , "Thu");}
|
||||
@Test public void Utc_ymd() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|20120102}}" , "2012-01-02");}
|
||||
@Test public void Utc_ym() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|201201}}" , "2012-01-01");}
|
||||
@Test public void Utc_md() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|2-13}}" , "2012-02-13");} // PURPOSE.fix: m-d failed
|
||||
@Test public void Slashes() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|2/13/12}}" , "2012-02-13");} // PURPOSE: assert slashes work
|
||||
@Test public void Utc_day() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|March 27}}" , "2012-03-27");}
|
||||
@Test public void Parse_day() {fxt.Test_parse_tmpl_str("{{#time:m d|March 27}}" , "03 27");}
|
||||
@Test public void Month_name() {fxt.Test_parse_tmpl_str("{{#time:M|May 1 2012}}" , "May");}
|
||||
@Test public void Time_before_date__dmy() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d H:i|04:50, 17 December 2010}}" , "2010-12-17 04:50");} // PAGE:en.w:Talk:Battle of Fort Washington
|
||||
@Test public void Time_before_date__mdy() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d H:i|04:50, December 11, 2010}}" , "2010-12-11 04:50");} // PAGE:en.w:Wikipedia:WikiProject_Maine/members; DATE:2014-06-25
|
||||
@Test public void Error() {fxt.Test_parse_tmpl_str("{{#time:M|2}}" , "<strong class=\"error\">Invalid year: 2</strong>");}
|
||||
@Test public void Error2() {fxt.Test_parse_tmpl_str("{{#time:Y|July 28 - August 1, 1975}}" , "<strong class=\"error\">Invalid time</strong>");}
|
||||
@Test public void Error3() {fxt.Test_parse_tmpl_str("{{#time:Y|106BC-43BC}}" , "<strong class=\"error\">Invalid time</strong>");}
|
||||
@Test public void Timestamp() {fxt.Test_parse_tmpl_str("{{#time:F j, Y|20060827072854}}" , "August 27, 2006");} // PAGE:en.w:Great Fire of London
|
||||
@Test public void Unixtime_read() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d h:i:s A|@0}}" , "1970-01-01 12:00:00 AM");} // EX:w:Wikipedia:WikiProject_Articles_for_creation/BLD_Preload
|
||||
@Test public void Unixtime_read_neg() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d h:i:s A|@-3600}}" , "1969-12-31 11:00:00 PM");} // EX:w:Wikipedia:WikiProject_Articles_for_creation/October_-_November_2012_Backlog_Elimination_Drive; DATE:2014-05-10
|
||||
@Test public void Unixtime_8_digit() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d h:i:s A|@20120304}}" , "1970-08-21 08:58:24 PM");} // PURPOSE: make sure yyyy-MM-dd is gobbled by "@" and not evaluated again as date; EX:w:Wikipedia:WikiProject_Articles_for_creation/October_-_November_2012_Backlog_Elimination_Drive; DATE:2014-05-10
|
||||
@Test public void Unixtime_write() {fxt.Test_parse_tmpl_str("{{#time:U|2012-08-02}}" , "1343865600");} // PAGE:en.w:Opa (programming language)
|
||||
@Test public void Year_4_digit() {fxt.Test_parse_tmpl_str("{{#time:Y|June 20, 451}}" , "0451");} // PAGE:en.w:Battle of the Catalaunian Plains
|
||||
@Test public void Year_month() {fxt.Test_parse_tmpl_str("{{#time:F Y|November 2012}}" , "November 2012");} // PAGE:en.w:Project:Current events
|
||||
@Test public void Day_addition_with_dash(){fxt.Test_parse_tmpl_str("{{#time:Y-m-d|2011-11-13 +1 day}}" , "2011-11-14");} // PURPOSE: +1 day was becoming -1 day b/c it was picking up - at -13; PAGE:en.w:Template:POTD/2012-10-09
|
||||
@Test public void Hour_zero() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d H:i|August 18 2006 00:14}}" , "2006-08-18 00:14");} // PURPOSE: fix; invalid hour; PAGE:en.w:Talk:Martin Luther
|
||||
@Test public void Iso() {fxt.Test_parse_tmpl_str("{{#time:c|2012-01-02 03:04:05}}" , "2012-01-02T03:04:05-05:00");}
|
||||
@Test public void Ymdh() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|2012-01-02-99}}" , "2012-01-06");} // PURPOSE: "99" is treated as 99th hour; EX:w:LimeWire; DATE:2014-03-24
|
||||
@Test public void Ymdh_noop() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|2012-01-02-100}}" , "2012-01-02");} // PURPOSE: "100" is ignored
|
||||
@Test public void Month_is_0() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|2012-00-01}}" , "2011-12-01");} // PURPOSE: "0" for month is treated as -1; EX:w:Mariyinsky_Palace; DATE:2014-03-25
|
||||
@Test public void Day_is_0() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|2012-12-00}}" , "2012-11-30");} // PURPOSE: "0" for day is treated as -1; EX:w:Mariyinsky_Palace; DATE:2014-03-25
|
||||
@Test public void Day_suffix_y() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|11th Dec 2013}}" , "2013-12-11");} // PURPOSE: ignore suffix days; EX:11th; DATE:2014-03-25
|
||||
@Test public void Day_suffix_n() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|32nd Dec 2013}}" , "<strong class=\"error\">Invalid day: 32</strong>");}
|
||||
@Test public void Day_rel_today() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|today}}" , "2012-01-02");}
|
||||
@Test public void Day_rel_tomorrow() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|tomorrow}}" , "2012-01-03");}
|
||||
@Test public void Day_rel_yesterday() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|yesterday}}" , "2012-01-01");}
|
||||
@Test public void Unit_rel_year_next() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|next year}}" , "2013-01-02");} // DATE:2014-05-02
|
||||
@Test public void Unit_rel_year_last() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|last year}}" , "2011-01-02");}
|
||||
@Test public void Unit_rel_year_previous(){fxt.Test_parse_tmpl_str("{{#time:Y-m-d|previous year}}" , "2011-01-02");}
|
||||
@Test public void Unit_rel_year_this() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|this year}}" , "2012-01-02");}
|
||||
@Test public void Time_rel_now() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d h:i:s A|now}}" , "2012-01-02 03:05:05 AM");} // NOTE: minute is 5, not 4, b/c each call to DateAdp_.Now() automatically increments by 1 minute; DATE:2014-04-13
|
||||
@Test public void Empty_is_today() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|}}" , "2012-01-02");} // tested on MW
|
||||
@Test public void Day_name_today() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|Monday}}" , "2012-01-02");} // 2012-01-02 is Monday, so return Monday; DATE:2014-05-02
|
||||
@Test public void Day_name_future_1() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|Saturday}}" , "2012-01-07");} // return next Sunday; DATE:2014-05-02
|
||||
@Test public void Day_name_future_2() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|Sunday}}" , "2012-01-08");} // return next Saturday; DATE:2014-05-02
|
||||
@Test public void Day_name_dow() {fxt.Test_parse_tmpl_str("{{#time:w|Monday}}" , "1");}
|
||||
@Test public void Timezone_offset() {
|
||||
DateAdp.Timezone_offset_test = -18000;
|
||||
fxt.Test_parse_tmpl_str("{{#time:Z|}}" , "-18000");
|
||||
DateAdp.Timezone_offset_test = Int_.MinValue;
|
||||
} // Z=timezone offset in seconds; http://php.net/manual/en/function.date.php;
|
||||
@Test public void Timezone_plus() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d H:i:s|2012-01-02 03:04:05+06:30}}" , "2012-01-02 09:34:05");} // PURPOSE: handle timezone plus ; EX: +01:30; DATE:2014-08-26
|
||||
@Test public void Timezone_minus() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d H:i:s|2012-01-02 09:34:05-06:30}}" , "2012-01-02 03:04:05");} // PURPOSE: handle timezone minus; EX: -01:30; DATE:2014-08-26
|
||||
@Test public void Timezone_wrap() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d H:i:s|2012-01-31 22:30:05+01:30}}" , "2012-02-01 00:00:05");} // PURPOSE: handle timezone wrap ; DATE:2014-08-26
|
||||
@Test public void Rfc5322() {fxt.Test_parse_tmpl_str("{{#time:r|}}" , "Mon, 02 Jan 2012 08:04:05 +0000");}
|
||||
@Test public void Lang() {
|
||||
Xol_lang fr_lang = fxt.App().Lang_mgr().Get_by_key_or_new(Bry_.new_a7("fr"));
|
||||
Xol_msg_itm msg_itm = fr_lang.Msg_mgr().Itm_by_key_or_new(Bry_.new_a7("January"));
|
||||
msg_itm.Atrs_set(Bry_.new_a7("Janvier"), false, false);
|
||||
fxt.Test_parse_tmpl_str("{{#time:F|2012-01|fr}}" , "Janvier");
|
||||
// fxt.Test_parse_tmpl_str("{{#time:F|2012-01|fr_bad}}" , "January"); // default to english // commented out; fails when running all at once
|
||||
}
|
||||
@Test public void Hour_with_dash() {fxt.Test_parse_tmpl_str("{{#time:c|January 2, 2001-06}}" , "2001-01-02T06:00:00-05:00");} // PURPOSE.fix: w:Vim_(text_editor) generates this during {{time ago|November 2, 1991-06-19|min_magnitude=days}}; DATE:2013-06-19
|
||||
@Test public void Multiple_dates_gt_12() {fxt.Test_parse_tmpl_str("{{#time:c|January 2, 2001-06-19}}" , "2001-01-02T06:00:00-05:00");} // PURPOSE.fix: w:Vim_(text_editor)
|
||||
@Test public void Multiple_dates_lt_12() {fxt.Test_parse_tmpl_str("{{#time:c|January 2, 2001-06-11}}" , "2001-01-02T06:00:00-05:00");} // PURPOSE.fix: w:Vim_(text_editor)
|
||||
@Test public void Raw_H() {fxt.Test_parse_tmpl_str("{{#time:xnH}}" , "08");} // PURPOSE: ignore "xn" for now; chk 0-padded number is generated; DATE:2013-12-31
|
||||
@Test public void Raw_h() {fxt.Test_parse_tmpl_str("{{#time:xnh}}" , "08");} // PURPOSE: ignore "xn" for now; chk 0-padded number is generated; DATE:2013-12-31
|
||||
@Test public void Iso8601_T() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d h:i:s A|T1:23}}" , "2012-01-01 01:23:00 AM");} // handle "T" flag; PAGE:pl.w:StarCraft_II:_Wings_of_Liberty
|
||||
@Test public void Iso8601_T_ws() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d h:i:s A|T 1:23}}" , "2012-01-01 01:23:00 AM");} // handle "T" flag and ws
|
||||
@Test public void Iso8601_T_fail() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d h:i:s A|T2012-01-02}}" , "<strong class=\"error\">Invalid hour: T</strong>");} // handle "T" flag and ws
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pft_func_time_foreign_tst {
|
||||
@Before public void init() {fxt.Clear();} private Pft_func_time_foreign_fxt fxt = new Pft_func_time_foreign_fxt();
|
||||
@After public void term() {fxt.Term();}
|
||||
@Test public void Roman() {fxt.Test_parse("{{#time:xrY|2012}}" , "MMXII");}
|
||||
@Test public void Thai() {fxt.Test_parse("{{#time:xkY|2012}}" , "2555");}
|
||||
@Test public void Minguo() {fxt.Test_parse("{{#time:xoY|2012}}" , "101");}
|
||||
@Test public void Hebrew_year_num() {fxt.Test_parse("{{#time:xjY|2012-01-02}}" , "5772");}
|
||||
@Test public void Hebrew_month_num() {fxt.Test_parse("{{#time:xjn|2012-01-02}}" , "4");}
|
||||
@Test public void Hebrew_day_num() {fxt.Test_parse("{{#time:xjj|2012-01-02}}" , "7");}
|
||||
@Test public void Hebrew_month_days_count() {fxt.Test_parse("{{#time:xjt|2012-01-02}}" , "29");}
|
||||
@Test public void Hebrew_month_name_full() {fxt.Init_msg("hebrew-calendar-m4" , "Tevet").Test_parse("{{#time:xjF|2012-01-02}}" , "Tevet");}
|
||||
@Test public void Hebrew_month_name_gen() {fxt.Init_msg("hebrew-calendar-m4-gen" , "Tevet").Test_parse("{{#time:xjx|2012-01-02}}" , "Tevet");}
|
||||
@Test public void Hebrew_numeral() {fxt.Test_parse("{{#time:xh}}" , "");}
|
||||
@Test public void Hebrew_numeral_2() {fxt.Test_parse("{{#time:xhxjY|2014}}" , "ה'תשע\"ד");}
|
||||
@Test public void Roman_various() {
|
||||
fxt.Test_Roman( 1, "I");
|
||||
fxt.Test_Roman( 2, "II");
|
||||
fxt.Test_Roman( 3, "III");
|
||||
fxt.Test_Roman( 4, "IV");
|
||||
fxt.Test_Roman( 5, "V");
|
||||
fxt.Test_Roman( 6, "VI");
|
||||
fxt.Test_Roman( 7, "VII");
|
||||
fxt.Test_Roman( 8, "VIII");
|
||||
fxt.Test_Roman( 9, "IX");
|
||||
fxt.Test_Roman( 10, "X");
|
||||
fxt.Test_Roman( 11, "XI");
|
||||
fxt.Test_Roman( 100, "C");
|
||||
fxt.Test_Roman( 101, "CI");
|
||||
fxt.Test_Roman( 111, "CXI");
|
||||
fxt.Test_Roman(1000, "M");
|
||||
fxt.Test_Roman(1001, "MI");
|
||||
fxt.Test_Roman(4000, "4000");
|
||||
}
|
||||
}
|
||||
class Pft_func_time_foreign_fxt {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
public void Clear() {
|
||||
fxt.Reset();
|
||||
Tfds.Now_set(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));
|
||||
}
|
||||
public void Term() {
|
||||
Tfds.Now_enabled_n_();
|
||||
}
|
||||
public Pft_func_time_foreign_fxt Init_msg(String key, String val) {
|
||||
Xol_msg_itm msg = fxt.Wiki().Msg_mgr().Get_or_make(Bry_.new_u8(key));
|
||||
msg.Atrs_set(Bry_.new_u8(val), false, false);
|
||||
return this;
|
||||
}
|
||||
public void Test_parse(String raw, String expd) {
|
||||
fxt.Test_parse_tmpl_str_test(raw, "{{test}}", expd);
|
||||
}
|
||||
public void Test_Roman(int v, String expd) {
|
||||
Bry_bfr bfr = Bry_bfr.new_(16);
|
||||
Pfxtp_roman.ToRoman(v, bfr);
|
||||
String actl = bfr.Xto_str_and_clear();
|
||||
Tfds.Eq(expd, actl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pft_func_time_int_tst {
|
||||
@Before public void init() {fxt.Reset(); Tfds.Now_set(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));} private Xop_fxt fxt = new Xop_fxt();
|
||||
@Test public void Time_before_date__dmy() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d H:i|01:02 3.4.2005}}" , "2005-04-03 01:02");} // PAGE:sk.w:Dr._House; DATE:2014-09-23
|
||||
@Test public void Time_before_date__mdy() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d H:i|01:02 3.14.2005}}" , "<strong class=\"error\">Invalid month: 14</strong>");} // mdy is invalid; DATE:2014-09-23
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pft_func_time_uncommon_tst {
|
||||
private Xop_fxt fxt = new Xop_fxt();
|
||||
@Before public void init() {fxt.Reset(); Tfds.Now_set(DateAdp_.new_(2012, 1, 2, 3, 4, 5, 6));}
|
||||
@After public void term() {Tfds.Now_enabled_n_();}
|
||||
@Test public void Year_5_digits() {fxt.Test_parse_tmpl_str_test("{{#time:Y-m-d|00123-4-5}}" , "{{test}}" , "2003-04-05");} // PURPOSE: emulate PHP's incorrect date parsing; EX:ca.w:Nicolau_de_Mira; DATE:2014-04-17
|
||||
}
|
||||
209
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_eval_seg.java
Normal file
209
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_eval_seg.java
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
class Pxd_eval_year {
|
||||
public static void Eval_at_pos_0(Pxd_parser tctx, Pxd_itm_int cur) {
|
||||
Pxd_itm[] data_ary = tctx.Data_ary();
|
||||
if (tctx.Data_ary_len() < 2) return;
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
if (itm_1 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, itm_1)) return;
|
||||
}
|
||||
if (tctx.Data_ary_len() < 3) return;
|
||||
Pxd_itm_int itm_2 = Pxd_itm_int_.CastOrNull(data_ary[2]);
|
||||
if (itm_2 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_d(tctx, itm_2)) return;
|
||||
}
|
||||
if (tctx.Data_ary_len() == 4) { // handle strange constructions like 2014-03-24-25;
|
||||
Pxd_itm_int itm_3 = Pxd_itm_int_.CastOrNull(data_ary[3]);
|
||||
if (itm_3 != null) { // treat 4th number as hour adjustment; EX: 2014-03-24-72 -> 2014-03-26; DATE:2014-03-24
|
||||
int itm_3_val = itm_3.Val();
|
||||
if (itm_3_val > 99) itm_3_val = 0; // only adjust if number is between 0 and 99;
|
||||
Pxd_itm_int_.Convert_to_rel(tctx, itm_3, Pxd_parser_.Unit_name_hour, DateAdp_.SegIdx_hour, itm_3_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void Eval_at_pos_2(Pxd_parser tctx, Pxd_itm_int cur) {
|
||||
Pxd_itm[] data_ary = tctx.Data_ary();
|
||||
Pxd_itm_int itm_0 = Pxd_itm_int_.CastOrNull(data_ary[0]);
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
if (itm_0 == null || itm_1 == null) return; // 0 or 1 is not an int;
|
||||
if (itm_1.Val() > 13) {
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, itm_0)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_d(tctx, itm_1)) return;
|
||||
}
|
||||
else {
|
||||
if (!Pxd_eval_seg.Eval_as_d(tctx, itm_0)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, itm_1)) return;
|
||||
}
|
||||
}
|
||||
public static void Eval_at_pos_n(Pxd_parser tctx, Pxd_itm_int cur) { // where n > 2; EX: 1:23 4.5.2010; PAGE:sk.w:Dr._House; DATE:2014-09-23
|
||||
Pxd_itm[] data_ary = tctx.Data_ary(); int data_ary_len = data_ary.length; int data_idx = cur.Data_idx();
|
||||
Pxd_itm_int lhs_1 = Pxd_itm_int_.Get_int_bwd(data_ary, data_ary_len, data_idx - 1);
|
||||
if (lhs_1 != null) { // lhs_1 is int; EX:05-2014
|
||||
Pxd_itm_int lhs_0 = Pxd_itm_int_.Get_int_bwd(data_ary, data_ary_len, data_idx - 2);
|
||||
if (lhs_0 != null) { // lhs_0 is int; EX:01-05-2014
|
||||
if (!Pxd_eval_seg.Eval_as_d(tctx, lhs_0)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, lhs_1)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_y(tctx, cur )) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static final int Month_max = 12;
|
||||
}
|
||||
class Pxd_eval_seg {
|
||||
public static boolean Eval_as_y(Pxd_parser tctx, Pxd_itm_int itm) {
|
||||
int val = itm.Val();
|
||||
switch (itm.Digits()) {
|
||||
case 1:
|
||||
case 2:
|
||||
itm.Val_(val + (val > 69 ? 1900 : 2000)); // assume that 70 refers to 1970 and 69 refers to 2069
|
||||
tctx.Seg_idxs_(itm, DateAdp_.SegIdx_year);
|
||||
return true;
|
||||
case 3: // NOTE: 3 digit numbers are valid years; MW relies on PHP time parse which always zero-pad numbers; PAGE:en.w:Battle of the Catalaunian Plains; {{#time:Y|June 20, 451}}
|
||||
case 4:
|
||||
tctx.Seg_idxs_(itm, DateAdp_.SegIdx_year);
|
||||
return true;
|
||||
}
|
||||
tctx.Err_set(Pft_func_time_log.Invalid_year, Bry_fmtr_arg_.int_(val));
|
||||
return false;
|
||||
}
|
||||
public static boolean Eval_as_m(Pxd_parser tctx, Pxd_itm_int itm) {
|
||||
int val = itm.Val();
|
||||
switch (itm.Digits()) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (val > 0 && val < 13) {
|
||||
tctx.Seg_idxs_(itm, DateAdp_.SegIdx_month);
|
||||
return true;
|
||||
}
|
||||
else if (val == 0) {// 0 day means subtract 1; EX:w:Mariyinsky_Palace; DATE:2014-03-25
|
||||
Pxd_itm_int_.Convert_to_rel(tctx, itm, Pxd_parser_.Unit_name_month, DateAdp_.SegIdx_month, -1);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tctx.Err_set(Pft_func_time_log.Invalid_month, Bry_fmtr_arg_.int_(val));
|
||||
return false;
|
||||
}
|
||||
public static boolean Eval_as_d(Pxd_parser tctx, Pxd_itm_int itm) {
|
||||
int val = itm.Val();
|
||||
switch (itm.Digits()) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (val > 0 && val < 32) {
|
||||
tctx.Seg_idxs_(itm, DateAdp_.SegIdx_day);
|
||||
return true;
|
||||
}
|
||||
else if (val == 0) { // 0 day means subtract 1; EX:w:Mariyinsky_Palace; DATE:2014-03-25
|
||||
Pxd_itm_int_.Convert_to_rel(tctx, itm, Pxd_parser_.Unit_name_day, DateAdp_.SegIdx_day, -1);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tctx.Err_set(Pft_func_time_log.Invalid_day, Bry_fmtr_arg_.int_(val));
|
||||
return false;
|
||||
}
|
||||
public static boolean Eval_as_h(Pxd_parser tctx, Pxd_itm_int itm) {
|
||||
int val = itm.Val();
|
||||
switch (itm.Digits()) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (val > -1 && val < 25) {
|
||||
tctx.Seg_idxs_(itm, DateAdp_.SegIdx_hour, val);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tctx.Err_set(Pft_func_time_log.Invalid_hour, Bry_fmtr_arg_.int_(val));
|
||||
return false;
|
||||
}
|
||||
public static boolean Eval_as_n(Pxd_parser tctx, Pxd_itm_int itm) {
|
||||
int val = itm.Val();
|
||||
switch (itm.Digits()) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (val > -1 && val < 60) {
|
||||
tctx.Seg_idxs_(itm, DateAdp_.SegIdx_minute, val);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tctx.Err_set(Pft_func_time_log.Invalid_minute, Bry_fmtr_arg_.int_(val));
|
||||
return false;
|
||||
}
|
||||
public static boolean Eval_as_s(Pxd_parser tctx, Pxd_itm_int itm) {
|
||||
int val = itm.Val();
|
||||
switch (itm.Digits()) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (val > -1 && val < 60) {
|
||||
tctx.Seg_idxs_(itm, DateAdp_.SegIdx_second);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tctx.Err_set(Pft_func_time_log.Invalid_second, Bry_fmtr_arg_.int_(val));
|
||||
return false;
|
||||
}
|
||||
public static boolean Eval_as_tz_h(Pxd_parser tctx, Pxd_itm_int itm, boolean negative) {
|
||||
if (negative) itm.Val_(itm.Val() * -1);
|
||||
int val = itm.Val();
|
||||
switch (itm.Digits()) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (val > -12 && val < 12) {
|
||||
itm.Val_is_adj_(Bool_.Y);
|
||||
itm.Seg_idx_(DateAdp_.SegIdx_hour);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tctx.Err_set(Pft_func_time_log.Invalid_hour, Bry_fmtr_arg_.int_(val));
|
||||
return false;
|
||||
}
|
||||
public static boolean Eval_as_tz_m(Pxd_parser tctx, Pxd_itm_int itm, boolean negative) {
|
||||
int val = itm.Val();
|
||||
if (negative) val *= -1;
|
||||
switch (itm.Digits()) {
|
||||
case 1:
|
||||
case 2:
|
||||
if (val > -60 && val < 60) {
|
||||
itm.Val_is_adj_(Bool_.Y);
|
||||
itm.Seg_idx_(DateAdp_.SegIdx_minute);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
tctx.Err_set(Pft_func_time_log.Invalid_minute, Bry_fmtr_arg_.int_(val));
|
||||
return false;
|
||||
}
|
||||
public static byte Eval_as_tz_sym(Pxd_parser tctx, Pxd_itm[] tkns, Pxd_itm_int hour_itm) {
|
||||
Pxd_itm sym = Pxd_itm_.Find_bwd__non_ws(tkns, hour_itm.Ary_idx());
|
||||
switch (sym.Tkn_tid()) {
|
||||
case Pxd_itm_.Tid_sym:
|
||||
Pxd_itm_sym sym_itm = (Pxd_itm_sym)sym;
|
||||
if (sym_itm.Sym_byte() == Byte_ascii.Plus)
|
||||
return Bool_.Y_byte;
|
||||
break;
|
||||
case Pxd_itm_.Tid_dash: return Bool_.N_byte;
|
||||
}
|
||||
tctx.Err_set(Pft_func_time_log.Invalid_timezone, Bry_fmtr_arg_.bry_("null"));
|
||||
return Bool_.__byte;
|
||||
}
|
||||
}
|
||||
122
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_.java
Normal file
122
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_.java
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
interface Pxd_itm {
|
||||
byte Tkn_tid();
|
||||
int Ary_idx();
|
||||
int Seg_idx();
|
||||
int Eval_idx();
|
||||
int Data_idx(); void Data_idx_(int v);
|
||||
void Eval(Pxd_parser state);
|
||||
void Time_ini(DateAdpBldr bldr);
|
||||
}
|
||||
class Pxd_itm_ {
|
||||
public static final int
|
||||
Tid_null = 0
|
||||
, Tid_int = 1
|
||||
, Tid_int_dmy_14 = 2
|
||||
, Tid_int_hms_6 = 3
|
||||
, Tid_month_name = 4
|
||||
, Tid_dow_name = 5
|
||||
, Tid_unit = 6
|
||||
, Tid_ago = 7
|
||||
, Tid_day_suffix = 8 // 1st, 2nd
|
||||
, Tid_day_relative = 9 // today, tomorrow, yesterday
|
||||
, Tid_time_relative = 10 // now
|
||||
, Tid_unit_relative = 11 // next, previous
|
||||
, Tid_unixtime = 12 // @123
|
||||
, Tid_iso8601_t = 13 // T
|
||||
, Tid_dash = Byte_ascii.Dash
|
||||
, Tid_dot = Byte_ascii.Dot
|
||||
, Tid_slash = Byte_ascii.Slash
|
||||
, Tid_colon = Byte_ascii.Colon
|
||||
, Tid_ws = 98
|
||||
, Tid_sym = 99
|
||||
;
|
||||
public static Pxd_itm Find_bwd__non_ws(Pxd_itm[] tkns, int bgn) {
|
||||
for (int i = bgn - 1; i > -1; --i) {
|
||||
Pxd_itm itm = tkns[i];
|
||||
if (itm.Tkn_tid() != Tid_ws) return itm;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static Pxd_itm Find_fwd_by_tid(Pxd_itm[] tkns, int bgn, int tid) {
|
||||
int len = tkns.length;
|
||||
for (int i = bgn; i < len; i++) {
|
||||
Pxd_itm itm = tkns[i];
|
||||
if (tid == itm.Tkn_tid()) return itm;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static boolean Eval_needed(Pxd_itm itm) {return itm.Seg_idx() == -1;}
|
||||
}
|
||||
abstract class Pxd_itm_base implements Pxd_itm {
|
||||
public abstract byte Tkn_tid();
|
||||
public int Ary_idx() {return ary_idx;} private int ary_idx;
|
||||
public int Seg_idx() {return seg_idx;} private int seg_idx = Seg_idx_null;
|
||||
public void Seg_idx_(int v) {seg_idx = v;}
|
||||
public int Data_idx() {return data_idx;} public void Data_idx_(int v) {data_idx = v;} private int data_idx;
|
||||
public abstract int Eval_idx();
|
||||
@gplx.Virtual public void Eval(Pxd_parser state) {}
|
||||
@gplx.Virtual public void Time_ini(DateAdpBldr bldr) {}
|
||||
public void Ctor(int ary_idx) {this.ary_idx = ary_idx;}
|
||||
public static final int Seg_idx_null = -1, Seg_idx_skip = -2;
|
||||
}
|
||||
interface Pxd_itm_prototype {
|
||||
Pxd_itm MakeNew(int ary_idx);
|
||||
}
|
||||
class DateAdpBldr {
|
||||
public DateAdp Date() {
|
||||
if (dirty) {
|
||||
if (date == null) date = DateAdp_.seg_(seg_ary); // date not set and seg_ary is dirty; make date = seg_ary;
|
||||
return date;
|
||||
}
|
||||
else
|
||||
return DateAdp_.Now(); // not dirtied; default to now;
|
||||
}
|
||||
public DateAdpBldr Date_(DateAdp v) {date = v; return this;} DateAdp date = null;
|
||||
public DateAdpBldr Seg_set(int idx, int val) {
|
||||
if (date == null) seg_ary[idx] = val;
|
||||
else {
|
||||
seg_ary = date.XtoSegAry();
|
||||
seg_ary[idx] = val;
|
||||
date = DateAdp_.seg_(seg_ary);
|
||||
}
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
public DateAdp Bld() {
|
||||
return date == null ? DateAdp_.seg_(seg_ary) : date;
|
||||
}
|
||||
public DateAdpBldr(int... seg_ary) {this.seg_ary = seg_ary;}
|
||||
int[] seg_ary = new int[DateAdp_.SegIdx__max]; boolean dirty = false;
|
||||
}
|
||||
class Pft_func_time_log {
|
||||
private static final Gfo_msg_grp owner = Gfo_msg_grp_.new_(Xoa_app_.Nde, "time_parser");
|
||||
public static final Gfo_msg_itm
|
||||
Invalid_day = Gfo_msg_itm_.new_warn_(owner, "Invalid day: ~{0}")
|
||||
, Invalid_month = Gfo_msg_itm_.new_warn_(owner, "Invalid month: ~{0}")
|
||||
, Invalid_year = Gfo_msg_itm_.new_warn_(owner, "Invalid year: ~{0}")
|
||||
, Invalid_year_mid = Gfo_msg_itm_.new_warn_(owner, "Invalid date: 4 digit year must be either yyyy-##-## or ##-##-yyyy")
|
||||
, Invalid_hour = Gfo_msg_itm_.new_warn_(owner, "Invalid hour: ~{0}")
|
||||
, Invalid_minute = Gfo_msg_itm_.new_warn_(owner, "Invalid minute: ~{0}")
|
||||
, Invalid_second = Gfo_msg_itm_.new_warn_(owner, "Invalid second: ~{0}")
|
||||
, Invalid_date = Gfo_msg_itm_.new_warn_(owner, "Invalid date: ~{0}")
|
||||
, Invalid_timezone = Gfo_msg_itm_.new_warn_(owner, "Invalid timezone: ~{0}")
|
||||
;
|
||||
}
|
||||
299
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_int.java
Normal file
299
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_int.java
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
interface Pxd_itm_int_interface extends Pxd_itm {
|
||||
int Xto_int_or(int or);
|
||||
}
|
||||
class Pxd_itm_int extends Pxd_itm_base implements Pxd_itm_int_interface {
|
||||
public Pxd_itm_int(int ary_idx, int digits, int val) {
|
||||
this.Ctor(ary_idx); this.digits = digits; this.val = val;
|
||||
switch (digits) {
|
||||
case 4: // assume year
|
||||
eval_idx = 50;
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
default:
|
||||
if (val > 12) // either day or year; not month
|
||||
eval_idx = 60;
|
||||
else
|
||||
eval_idx = 70; // day, year, or month
|
||||
break;
|
||||
}
|
||||
}
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_int;}
|
||||
@Override public int Eval_idx() {return eval_idx;} private int eval_idx = 99;
|
||||
public int Val() {return val;} public Pxd_itm_int Val_(int v) {val = v; return this;} private int val;
|
||||
public boolean Val_is_adj() {return val_is_adj;} public void Val_is_adj_(boolean v) {val_is_adj = v;} private boolean val_is_adj;
|
||||
public int Xto_int_or(int or) {return val;}
|
||||
public int Digits() {return digits;} private int digits;
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
int seg_idx = this.Seg_idx();
|
||||
if (seg_idx == Pxd_itm_base.Seg_idx_skip) return;
|
||||
if (val_is_adj) {
|
||||
if (val == 0) return; // no adjustment to make
|
||||
DateAdp date = bldr.Date();
|
||||
switch (seg_idx) {
|
||||
case DateAdp_.SegIdx_hour: date = date.Add_hour(val); break;
|
||||
case DateAdp_.SegIdx_minute: date = date.Add_minute(val); break;
|
||||
default: return;
|
||||
}
|
||||
bldr.Date_(date);
|
||||
}
|
||||
else
|
||||
bldr.Seg_set(seg_idx, val);
|
||||
}
|
||||
@Override public void Eval(Pxd_parser tctx) {
|
||||
int data_idx = this.Data_idx();
|
||||
if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return; // has seg_idx; already eval'd by something else
|
||||
switch (digits) {
|
||||
case 5: // 5 digits
|
||||
switch (data_idx) {
|
||||
case 0: Pxd_eval_year.Eval_at_pos_0(tctx, this); break; // year at pos 0; EX: 01234-02-03
|
||||
case 1: tctx.Err_set(Pft_func_time_log.Invalid_date); return; // year at pos 1; invalid; EX: 01-01234-02
|
||||
case 2: tctx.Err_set(Pft_func_time_log.Invalid_date); break; // year at pos 2; invalid; EX: 01-02-01234
|
||||
}
|
||||
val = 2000 + (val % 10); // NOTE: emulate PHP's incorrect behavior with 5 digit years; EX:ca.w:Nicolau_de_Mira; DATE:2014-04-18
|
||||
tctx.Seg_idxs_(this, DateAdp_.SegIdx_year);
|
||||
break;
|
||||
case 4: // 4 digits; assume year
|
||||
switch (data_idx) {
|
||||
case 0: Pxd_eval_year.Eval_at_pos_0(tctx, this); break; // year at pos 0; EX: 2001-02-03
|
||||
case 1: tctx.Err_set(Pft_func_time_log.Invalid_year_mid); return;// year at pos 1; invalid; EX: 02-2003-03
|
||||
case 2: Pxd_eval_year.Eval_at_pos_2(tctx, this); break; // year at pos 2; EX: 02-03-2001
|
||||
default: Pxd_eval_year.Eval_at_pos_n(tctx, this); break; // year at pos n; EX: 04:05 02-03-2001
|
||||
}
|
||||
tctx.Seg_idxs_(this, DateAdp_.SegIdx_year);
|
||||
break;
|
||||
default:
|
||||
Pxd_itm[] data_ary = tctx.Data_ary();
|
||||
int data_ary_len = data_ary.length;
|
||||
Pxd_itm_int cur_itm = Pxd_itm_int_.CastOrNull(data_ary[data_idx]);
|
||||
Pxd_itm lhs_itm = data_idx == 0 ? null : data_ary[data_idx - 1];
|
||||
Pxd_itm rhs_itm = data_idx == data_ary_len - 1 ? null : data_ary[data_idx + 1];
|
||||
if ( lhs_itm != null && lhs_itm.Seg_idx() == DateAdp_.SegIdx_month // itm on left is month
|
||||
&& rhs_itm != null && rhs_itm.Seg_idx() == DateAdp_.SegIdx_year // itm on right is year
|
||||
&& tctx.Seg_idxs()[DateAdp_.SegIdx_day] == -1 // day not yet set; needed for {{#time:Y|July 28 - August 1, 1975}}
|
||||
)
|
||||
if (!Pxd_eval_seg.Eval_as_d(tctx, cur_itm)) return; // cur int should be day; EX:January 1, 2010; PAGE:en.w:Wikipedia:WikiProject_Maine/members; DATE:2014-06-25
|
||||
if (val > Month_max) { // value is not a month; assume day; DATE:2013-03-15
|
||||
switch (data_idx) {
|
||||
case 0: // > 12 in slot 0
|
||||
if (Match_sym(tctx, Bool_.Y, Pxd_itm_.Tid_dot)) // next sym is dot; assume m.d.y; EX: 22.5.70
|
||||
Eval_day_at_pos_0(tctx);
|
||||
else // next sym is not dot; assume y-m-d; EX: 70-5-22
|
||||
Eval_month_at_pos_0(tctx);
|
||||
break;
|
||||
case 1: Eval_month_at_pos_1(tctx); break; // > 12 in slot 1; assume m.d; EX: 5.22
|
||||
case 2: // > 12 in slot 2
|
||||
if (Match_sym(tctx, Bool_.N, Pxd_itm_.Tid_dot)) // prv sym is dot; assume d.m.y; EX: 22.5.70
|
||||
Eval_dmy_at_y(tctx);
|
||||
else // prv sym is not dot; assume m-d-y; EX: 22.5.70
|
||||
Eval_month_at_pos_2(tctx);
|
||||
break;
|
||||
case 4:
|
||||
Eval_unknown_at_pos_4(tctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else { // value is either day or month;
|
||||
switch (data_idx) {
|
||||
case 0: Eval_unknown_at_pos_0(tctx); break;
|
||||
case 3: Eval_unknown_at_pos_3(tctx); break;
|
||||
case 4: Eval_unknown_at_pos_4(tctx); break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
public static final int Month_max = 12;
|
||||
private void Eval_unknown_at_pos_3(Pxd_parser tctx) { // int at pos 4
|
||||
if ( tctx.Seg_idxs_chk(DateAdp_.SegIdx_year, DateAdp_.SegIdx_month, DateAdp_.SegIdx_day) // check that ymd is set
|
||||
&& Match_sym(tctx, false, Pxd_itm_.Tid_dash)) // check that preceding symbol is "-"
|
||||
Pxd_eval_seg.Eval_as_h(tctx, this); // mark as hour; handles strange fmts like November 2, 1991-06; DATE:2013-06-19
|
||||
}
|
||||
private void Eval_unknown_at_pos_4(Pxd_parser tctx) {
|
||||
if ( tctx.Seg_idxs_chk(DateAdp_.SegIdx_year
|
||||
, DateAdp_.SegIdx_month, DateAdp_.SegIdx_day, DateAdp_.SegIdx_hour) // check that ymdh is set
|
||||
&& Match_sym(tctx, false, Pxd_itm_.Tid_dash)) // check that preceding symbol is "-"
|
||||
tctx.Seg_idxs_(this, Pxd_itm_base.Seg_idx_skip); // mark as ignore; handles strange fmts like November 2, 1991-06-19; DATE:2013-06-19
|
||||
}
|
||||
boolean Match_sym(Pxd_parser tctx, boolean fwd, int sym_tid) {
|
||||
int sym_idx = this.Ary_idx() + (fwd ? 1 : -1);
|
||||
Pxd_itm[] sym_tkns = tctx.Tkns();
|
||||
if (sym_idx < 0 || sym_idx > sym_tkns.length) return false; // NOTE: was Data_ary_len; DATE:2013-06-19
|
||||
return sym_tkns[sym_idx].Tkn_tid() == sym_tid;
|
||||
}
|
||||
private void Eval_month_at_pos_0(Pxd_parser tctx) {
|
||||
Pxd_itm[] data_ary = tctx.Data_ary();
|
||||
if (tctx.Data_ary_len() < 2) return;
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
if (itm_1 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, itm_1)) return;
|
||||
}
|
||||
if (tctx.Data_ary_len() > 2) {
|
||||
Pxd_itm_int itm_2 = Pxd_itm_int_.CastOrNull(data_ary[2]);
|
||||
if (itm_2 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_d(tctx, itm_2)) return;
|
||||
}
|
||||
}
|
||||
Pxd_eval_seg.Eval_as_y(tctx, this);
|
||||
}
|
||||
private void Eval_day_at_pos_0(Pxd_parser tctx) { // eval 1 as month; 2 as year, 0 as day
|
||||
Pxd_itm[] data_ary = tctx.Data_ary();
|
||||
if (tctx.Data_ary_len() < 2) return;
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
if (itm_1 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, itm_1)) return;
|
||||
}
|
||||
if (tctx.Data_ary_len() > 2) {
|
||||
Pxd_itm_int itm_2 = Pxd_itm_int_.CastOrNull(data_ary[2]);
|
||||
if (itm_2 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_y(tctx, itm_2)) return;
|
||||
}
|
||||
}
|
||||
Pxd_eval_seg.Eval_as_d(tctx, this);
|
||||
}
|
||||
private void Eval_dmy_at_y(Pxd_parser tctx) { // dmy format; cur is y (slot 2)
|
||||
Pxd_itm[] data_ary = tctx.Data_ary();
|
||||
if (tctx.Data_ary_len() < 3) return; // since proc starts at y, assume at least d-m-y (not m-y)
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
if (itm_1 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, itm_1)) return;
|
||||
}
|
||||
Pxd_itm_int itm_0 = Pxd_itm_int_.CastOrNull(data_ary[0]);
|
||||
if (itm_0 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_y(tctx, itm_0)) return;
|
||||
}
|
||||
Pxd_eval_seg.Eval_as_y(tctx, this);
|
||||
}
|
||||
private void Eval_month_at_pos_1(Pxd_parser tctx) {
|
||||
Pxd_itm[] data_ary = tctx.Data_ary();
|
||||
Pxd_itm_int itm_0 = Pxd_itm_int_.CastOrNull(data_ary[0]);
|
||||
if (itm_0 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, itm_0)) return;
|
||||
}
|
||||
if (tctx.Data_ary_len() > 2) {
|
||||
Pxd_itm_int itm_2 = Pxd_itm_int_.CastOrNull(data_ary[2]);
|
||||
if (itm_2 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_y(tctx, itm_2)) return;
|
||||
}
|
||||
}
|
||||
Pxd_eval_seg.Eval_as_d(tctx, this);
|
||||
}
|
||||
private void Eval_month_at_pos_2(Pxd_parser tctx) {
|
||||
Pxd_itm[] data_ary = tctx.Data_ary();
|
||||
Pxd_itm_int itm_0 = Pxd_itm_int_.CastOrNull(data_ary[0]);
|
||||
if (itm_0 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, itm_0)) return;
|
||||
}
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
if (itm_1 != null) {
|
||||
if (!Pxd_eval_seg.Eval_as_d(tctx, itm_1)) return;
|
||||
}
|
||||
Pxd_eval_seg.Eval_as_y(tctx, this);
|
||||
}
|
||||
private void Eval_unknown_at_pos_0(Pxd_parser tctx) { // NOTE: assumes dmy format
|
||||
Pxd_itm[] data_ary = tctx.Data_ary();
|
||||
if (tctx.Data_ary_len() < 2) {tctx.Err_set(Pft_func_time_log.Invalid_year, Bry_fmtr_arg_.int_(val)); return;}
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
if (itm_1 != null) { // if 1st itm to right is number, parse it as month
|
||||
if (!Pxd_eval_seg.Eval_as_m(tctx, itm_1)) return;
|
||||
}
|
||||
if (tctx.Data_ary_len() > 2) {
|
||||
Pxd_itm_int itm_2 = Pxd_itm_int_.CastOrNull(data_ary[2]);
|
||||
if (itm_2 != null) { // if 2nd itm to right is number, assume it as year
|
||||
if (!Pxd_eval_seg.Eval_as_y(tctx, itm_2)) return;
|
||||
}
|
||||
}
|
||||
Pxd_eval_seg.Eval_as_d(tctx, this); // parse current as day (dmy format)
|
||||
}
|
||||
}
|
||||
class Pxd_itm_int_ {
|
||||
public static void Convert_to_rel(Pxd_parser tctx, Pxd_itm_int itm, byte[] unit_name, int seg_idx, int rel_val) {
|
||||
int tkn_idx = itm.Ary_idx();
|
||||
tctx.Tkns()[tkn_idx] = new Pxd_itm_unit(tkn_idx, unit_name, seg_idx, rel_val);
|
||||
}
|
||||
public static Pxd_itm_int CastOrNull(Pxd_itm itm) {return itm.Tkn_tid() == Pxd_itm_.Tid_int ? (Pxd_itm_int)itm : null; }
|
||||
public static Pxd_itm_int GetNearest(Pxd_itm[] tkns, int tkn_idx, boolean fwd) {
|
||||
int adj = 1, end = tkns.length;
|
||||
if (!fwd) {
|
||||
adj = -1;
|
||||
end = -1;
|
||||
}
|
||||
for (int i = tkn_idx + adj; i != end; i += adj) {
|
||||
Pxd_itm itm = tkns[i];
|
||||
if (itm.Tkn_tid() == Pxd_itm_.Tid_int) {
|
||||
Pxd_itm_int itm_int = (Pxd_itm_int)itm;
|
||||
return itm_int.Seg_idx() == -1 ? itm_int : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static int Read_nearest_as_int_and_skip(Pxd_parser tctx, Pxd_itm[] tkns, int bgn, boolean fwd, int or) {
|
||||
int adj = 1, end = tkns.length;
|
||||
if (!fwd) {
|
||||
adj = -1;
|
||||
end = -1;
|
||||
}
|
||||
Pxd_itm dash_itm = null;
|
||||
for (int i = bgn + adj; i != end; i += adj) {
|
||||
Pxd_itm itm = tkns[i];
|
||||
switch (itm.Tkn_tid()) {
|
||||
case Pxd_itm_.Tid_dash:
|
||||
dash_itm = itm; // TODO: throw error if "--"; {{#time:U|@--1}}
|
||||
break;
|
||||
case Pxd_itm_.Tid_int:
|
||||
case Pxd_itm_.Tid_int_dmy_14:
|
||||
case Pxd_itm_.Tid_int_hms_6:
|
||||
Pxd_itm_int_interface itm_int = (Pxd_itm_int_interface)itm;
|
||||
int itm_int_seg_idx = itm_int.Seg_idx();
|
||||
if (itm_int_seg_idx == -1) { // not evaluated
|
||||
int factor = 1;
|
||||
if (dash_itm != null) {
|
||||
tctx.Seg_idxs_((Pxd_itm_base)dash_itm, Pxd_itm_base.Seg_idx_skip, -1);
|
||||
factor = -1;
|
||||
}
|
||||
tctx.Seg_idxs_((Pxd_itm_base)itm, Pxd_itm_base.Seg_idx_skip, -1);
|
||||
return itm_int.Xto_int_or(or) * factor;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return or;
|
||||
}
|
||||
public static Pxd_itm_int Get_int_bwd(Pxd_itm[] data_ary, int data_ary_len, int idx) {
|
||||
if (idx > -1) { // make sure idx is > 0
|
||||
Pxd_itm rv = data_ary[idx]; // assume caller not passing in anything > ary.len
|
||||
if ( rv.Tkn_tid() == Pxd_itm_.Tid_int // rv is int
|
||||
&& Pxd_itm_.Eval_needed(rv) // rv needs evaluation
|
||||
)
|
||||
return (Pxd_itm_int)rv; // return it
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static Pxd_itm Get_int_fwd(Pxd_itm[] data_ary, int data_ary_len, int idx) {
|
||||
if (idx < data_ary_len) {
|
||||
Pxd_itm rv = data_ary[idx];
|
||||
if ( rv.Tkn_tid() == Pxd_itm_.Tid_int
|
||||
&& rv.Seg_idx() == -1)
|
||||
return rv;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
134
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_misc.java
Normal file
134
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_misc.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
class Pxd_itm_colon extends Pxd_itm_base {
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_colon;}
|
||||
@Override public int Eval_idx() {return 20;}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
int colon_count = ++state.Colon_count;
|
||||
Pxd_itm[] tkns = state.Tkns();
|
||||
Pxd_itm_int itm_int = null;
|
||||
switch (colon_count) {
|
||||
case 1: // hh:mm
|
||||
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), Bool_.N);
|
||||
if (itm_int == null) {state.Err_set(Pft_func_time_log.Invalid_hour, Bry_fmtr_arg_.bry_("null")); return;}
|
||||
if (!Pxd_eval_seg.Eval_as_h(state, itm_int)) return;
|
||||
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), true);
|
||||
if (!Pxd_eval_seg.Eval_as_n(state, itm_int)) return;
|
||||
break;
|
||||
case 2: // :ss
|
||||
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), true);
|
||||
if (!Pxd_eval_seg.Eval_as_s(state, itm_int)) return;
|
||||
break;
|
||||
case 3: // +hh:mm; DATE:2014-08-26
|
||||
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), Bool_.N);
|
||||
if (itm_int == null) {state.Err_set(Pft_func_time_log.Invalid_timezone, Bry_fmtr_arg_.bry_("null")); return;}
|
||||
byte tz_positive_val = Pxd_eval_seg.Eval_as_tz_sym(state, tkns, itm_int);
|
||||
if (tz_positive_val == Bool_.__byte) return;
|
||||
boolean tz_negative = tz_positive_val == Bool_.N_byte;
|
||||
if (!Pxd_eval_seg.Eval_as_tz_h(state, itm_int, tz_negative)) return;
|
||||
itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), Bool_.Y);
|
||||
if (itm_int == null) {state.Err_set(Pft_func_time_log.Invalid_timezone, Bry_fmtr_arg_.bry_("null")); return;}
|
||||
if (tz_negative) itm_int.Val_(itm_int.Val() * -1);
|
||||
if (!Pxd_eval_seg.Eval_as_tz_m(state, itm_int, tz_negative)) return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
public Pxd_itm_colon(int ary_idx) {this.Ctor(ary_idx);}
|
||||
}
|
||||
class Pxd_itm_null extends Pxd_itm_base {
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_null;}
|
||||
@Override public int Eval_idx() {return 99;}
|
||||
public static final Pxd_itm_null _ = new Pxd_itm_null();
|
||||
}
|
||||
class Pxd_itm_dash extends Pxd_itm_base {
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_dash;}
|
||||
@Override public int Eval_idx() {return 99;}
|
||||
public Pxd_itm_dash(int ary_idx) {this.Ctor(ary_idx);}
|
||||
}
|
||||
class Pxd_itm_dot extends Pxd_itm_base {
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_dot;}
|
||||
@Override public int Eval_idx() {return 99;}
|
||||
public Pxd_itm_dot(int ary_idx) {this.Ctor(ary_idx);}
|
||||
}
|
||||
class Pxd_itm_ws extends Pxd_itm_base {
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_ws;}
|
||||
@Override public int Eval_idx() {return 99;}
|
||||
public Pxd_itm_ws(int ary_idx) {this.Ctor(ary_idx);}
|
||||
}
|
||||
class Pxd_itm_slash extends Pxd_itm_base {
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_slash;}
|
||||
@Override public int Eval_idx() {return 99;}
|
||||
public Pxd_itm_slash(int ary_idx) {this.Ctor(ary_idx);}
|
||||
}
|
||||
class Pxd_itm_sym extends Pxd_itm_base {
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_sym;}
|
||||
@Override public int Eval_idx() {return 99;}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {}
|
||||
public byte Sym_byte() {return sym_byte;} private byte sym_byte;
|
||||
public Pxd_itm_sym(int ary_idx, byte val) {this.Ctor(ary_idx); this.sym_byte = val;}
|
||||
}
|
||||
class Pxd_itm_int_dmy_14 extends Pxd_itm_base implements Pxd_itm_int_interface {
|
||||
public Pxd_itm_int_dmy_14(int ary_idx, byte[] src, int digits) {this.Ctor(ary_idx); this.src = src; this.digits = digits;} private byte[] src; int digits;
|
||||
public int Xto_int_or(int or) {return Bry_.Xto_int_or(src, or);}
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_int_dmy_14;}
|
||||
@Override public int Eval_idx() {return eval_idx;} private int eval_idx = 20;
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return; // has seg_idx; already eval'd by something else
|
||||
bldr.Seg_set(DateAdp_.SegIdx_year , Bry_.Xto_int_or(src, 0, 4, 0));
|
||||
bldr.Seg_set(DateAdp_.SegIdx_month , Bry_.Xto_int_or(src, 4, 6, 0));
|
||||
if (digits > 6) {
|
||||
bldr.Seg_set(DateAdp_.SegIdx_day , Bry_.Xto_int_or(src, 6, 8, 0));
|
||||
if (digits > 8) {
|
||||
bldr.Seg_set(DateAdp_.SegIdx_hour , Bry_.Xto_int_or(src, 8, 10, 0));
|
||||
if (digits > 10) {
|
||||
bldr.Seg_set(DateAdp_.SegIdx_minute , Bry_.Xto_int_or(src, 10, 12, 0));
|
||||
if (digits > 12)
|
||||
bldr.Seg_set(DateAdp_.SegIdx_second , Bry_.Xto_int_or(src, 12, 14, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class Pxd_itm_int_mhs_6 extends Pxd_itm_base implements Pxd_itm_int_interface {
|
||||
public Pxd_itm_int_mhs_6(int ary_idx, byte[] src) {this.Ctor(ary_idx); this.src = src;} private byte[] src;
|
||||
public int Xto_int_or(int or) {return Bry_.Xto_int_or(src, or);}
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_int_hms_6;}
|
||||
@Override public int Eval_idx() {return eval_idx;} private int eval_idx = 20;
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return; // has seg_idx; already eval'd by something else
|
||||
bldr.Seg_set(DateAdp_.SegIdx_hour , Bry_.Xto_int_or(src, 0, 2, 0));
|
||||
bldr.Seg_set(DateAdp_.SegIdx_minute , Bry_.Xto_int_or(src, 2, 4, 0));
|
||||
bldr.Seg_set(DateAdp_.SegIdx_second , Bry_.Xto_int_or(src, 4, 6, 0));
|
||||
}
|
||||
}
|
||||
class Pxd_itm_sorter implements gplx.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Pxd_itm lhs = (Pxd_itm)lhsObj;
|
||||
Pxd_itm rhs = (Pxd_itm)rhsObj;
|
||||
return Int_.Compare(lhs.Eval_idx(), rhs.Eval_idx());
|
||||
}
|
||||
public static final Pxd_itm_sorter _ = new Pxd_itm_sorter();
|
||||
public static Pxd_itm[] XtoAryAndSort(Pxd_itm[] src, int src_len) {
|
||||
Pxd_itm[] rv = new Pxd_itm[src_len];
|
||||
for (int i = 0; i < src_len; i++)
|
||||
rv[i] = src[i];
|
||||
Array_.Sort(rv, Pxd_itm_sorter._);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
364
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_month_name.java
Normal file
364
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_month_name.java
Normal file
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
class Pxd_itm_month_name extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
public Pxd_itm_month_name(int ary_idx, byte[] name, int seg_idx, int seg_val) {Ctor(ary_idx); this.name = name; Seg_idx_(seg_idx); this.seg_val = seg_val;} private byte[] name;
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_month_name;}
|
||||
@Override public int Eval_idx() {return 20;}
|
||||
int seg_val;
|
||||
public Pxd_itm MakeNew(int ary_idx) {
|
||||
Pxd_itm_month_name rv = new Pxd_itm_month_name(ary_idx, name, this.Seg_idx(), seg_val);
|
||||
return rv;
|
||||
}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
state.Seg_idxs_(this, this.Seg_idx(), seg_val);
|
||||
switch (this.Data_idx()) {
|
||||
case 0: Eval_month_0(state); break;
|
||||
case 1: Eval_month_1(state); break;
|
||||
case 2: Eval_month_2(state); break;
|
||||
default:
|
||||
Pxd_itm[] data_ary = state.Data_ary();
|
||||
int data_idx = this.Data_idx();
|
||||
if (data_idx + 1 < data_ary.length) {
|
||||
Pxd_itm_int itm_rhs = Pxd_itm_int_.CastOrNull(data_ary[data_idx + 1]);
|
||||
if (itm_rhs.Digits() == 4) { // handle fmts of 1 January 2010
|
||||
Eval_month_1(state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Eval_month_2(state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
public void Eval_month_0(Pxd_parser state) {
|
||||
Pxd_itm[] data_ary = state.Data_ary();
|
||||
int data_ary_len = state.Data_ary_len();
|
||||
switch (data_ary_len) {
|
||||
case 1: break; // noop; nothing needs to be done
|
||||
case 2: {
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
if (itm_1 == null) {return;} // trie: fail
|
||||
switch (itm_1.Digits()) {
|
||||
case 4: Pxd_eval_seg.Eval_as_y(state, itm_1); break;
|
||||
default: Pxd_eval_seg.Eval_as_d(state, itm_1); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: // NOTE: handle invalid dates like January 2, 1999, 2000; DATE:2013-05-06
|
||||
case 3: {
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
Pxd_itm_int itm_2 = Pxd_itm_int_.CastOrNull(data_ary[2]);
|
||||
if (itm_1 == null || itm_2 == null) {return;} // trie: fail
|
||||
if (itm_1.Digits() == 4) { // ASSUME: year since there are 4 digits; EX: May 2012
|
||||
if (Pxd_eval_seg.Eval_as_y(state, itm_1)) return; // no error; return; otherwise continue below;
|
||||
}
|
||||
if (!Pxd_eval_seg.Eval_as_d(state, itm_1)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_y(state, itm_2)) return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Eval_month_1(Pxd_parser state) {
|
||||
Pxd_itm[] data_ary = state.Data_ary();
|
||||
int data_ary_len = state.Data_ary_len();
|
||||
switch (data_ary_len) {
|
||||
case 2: {
|
||||
Pxd_itm_int itm_0 = Pxd_itm_int_.CastOrNull(data_ary[0]);
|
||||
if (itm_0 == null) {return;} // trie: fail
|
||||
switch (itm_0.Digits()) {
|
||||
case 4: Pxd_eval_seg.Eval_as_y(state, itm_0); break;
|
||||
default: Pxd_eval_seg.Eval_as_d(state, itm_0); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case 3: {
|
||||
Pxd_itm_int itm_0 = Pxd_itm_int_.GetNearest(data_ary, this.Data_idx(), false);
|
||||
Pxd_itm_int itm_2 = Pxd_itm_int_.GetNearest(data_ary, this.Data_idx(), true);
|
||||
if (itm_0 == null || itm_2 == null) {return;} // trie: fail
|
||||
switch (itm_0.Digits()) {
|
||||
case 4:
|
||||
if (!Pxd_eval_seg.Eval_as_y(state, itm_0)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_d(state, itm_2)) return;
|
||||
break;
|
||||
default:
|
||||
if (itm_2.Digits() == 4) {
|
||||
if (!Pxd_eval_seg.Eval_as_d(state, itm_0)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_y(state, itm_2)) return;
|
||||
}
|
||||
else { // 2 digits on either side of month; assume dd mm yy; EX: 03 Feb 01 -> 2001-02-03
|
||||
if (!Pxd_eval_seg.Eval_as_d(state, itm_0)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_y(state, itm_2)) return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Eval_month_2(Pxd_parser state) {
|
||||
Pxd_itm[] data_ary = state.Data_ary();
|
||||
int data_ary_len = state.Data_ary_len();
|
||||
switch (data_ary_len) {
|
||||
case 3: {
|
||||
Pxd_itm_int itm_0 = Pxd_itm_int_.CastOrNull(data_ary[0]);
|
||||
Pxd_itm_int itm_1 = Pxd_itm_int_.CastOrNull(data_ary[1]);
|
||||
if (itm_0 == null || itm_1 == null) {return;} // trie: fail
|
||||
switch (itm_0.Digits()) {
|
||||
case 4:
|
||||
if (!Pxd_eval_seg.Eval_as_y(state, itm_0)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_d(state, itm_1)) return;
|
||||
break;
|
||||
default:
|
||||
if (itm_1.Digits() == 4) {
|
||||
if (!Pxd_eval_seg.Eval_as_d(state, itm_0)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_y(state, itm_1)) return;
|
||||
}
|
||||
else { // 2 digits on either side of month; assume dd mm yy; EX: 03 Feb 01 -> 2001-02-03
|
||||
if (!Pxd_eval_seg.Eval_as_d(state, itm_0)) return;
|
||||
if (!Pxd_eval_seg.Eval_as_y(state, itm_1)) return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
bldr.Seg_set(this.Seg_idx(), seg_val);
|
||||
}
|
||||
}
|
||||
class Pxd_itm_unit extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
public Pxd_itm_unit(int ary_idx, byte[] name, int seg_idx, int seg_multiple) {Ctor(ary_idx); this.name = name; Seg_idx_(seg_idx); this.seg_multiple = seg_multiple;}
|
||||
public byte[] Name() {return name;} private byte[] name;
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_unit;}
|
||||
@Override public int Eval_idx() {return 10;}
|
||||
int seg_val = 1; int seg_multiple;
|
||||
public Pxd_itm MakeNew(int ary_idx) {
|
||||
return new Pxd_itm_unit(ary_idx, name, this.Seg_idx(), seg_val);
|
||||
}
|
||||
public void Unit_seg_val_(int v) { // handled by relative; EX: next year
|
||||
seg_val = v; seg_multiple = 1;
|
||||
eval_done_by_relative = true;
|
||||
} private boolean eval_done_by_relative;
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
if (eval_done_by_relative) return;
|
||||
state.Seg_idxs_(this, this.Seg_idx(), seg_val);
|
||||
Pxd_itm[] tkns = state.Tkns();
|
||||
Pxd_itm_int itm_int = Pxd_itm_int_.GetNearest(tkns, this.Ary_idx(), false);
|
||||
state.Seg_idxs_(itm_int, Pxd_itm_base.Seg_idx_skip);
|
||||
seg_val = itm_int.Val();
|
||||
for (int i = itm_int.Ary_idx(); i > -1; i--) {
|
||||
Pxd_itm itm = tkns[i];
|
||||
switch (itm.Tkn_tid()) {
|
||||
case Pxd_itm_.Tid_dash: // negative sign; stop;
|
||||
seg_val *= -1;
|
||||
i = -1;
|
||||
break;
|
||||
case Pxd_itm_.Tid_dot: case Pxd_itm_.Tid_int: case Pxd_itm_.Tid_ws: // ignore
|
||||
break;
|
||||
default: // word; stop;
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
DateAdp cur = bldr.Date();
|
||||
if (cur == null) cur = DateAdp_.Now();
|
||||
int val = seg_val * seg_multiple;
|
||||
switch (this.Seg_idx()) {
|
||||
case DateAdp_.SegIdx_second: cur = cur.Add_second(val); break;
|
||||
case DateAdp_.SegIdx_minute: cur = cur.Add_minute(val); break;
|
||||
case DateAdp_.SegIdx_hour : cur = cur.Add_hour (val); break;
|
||||
case DateAdp_.SegIdx_day : cur = cur.Add_day (val); break;
|
||||
case DateAdp_.SegIdx_month : cur = cur.Add_month (val); break;
|
||||
case DateAdp_.SegIdx_year : cur = cur.Add_year (val); break;
|
||||
default: throw Exc_.new_unhandled(this.Seg_idx());
|
||||
}
|
||||
bldr.Date_(cur);
|
||||
}
|
||||
}
|
||||
class Pxd_itm_ago extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
public Pxd_itm_ago(int ary_idx, int seg_idx) {Ctor(ary_idx); Seg_idx_(seg_idx);}
|
||||
public byte[] Name() {return Name_ago;} public static final byte[] Name_ago = Bry_.new_a7("ago");
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_ago;}
|
||||
@Override public int Eval_idx() {return 5;} // set to high priority so it can evaluate before unit_name
|
||||
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_ago(ary_idx, this.Seg_idx());}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
Pxd_itm[] tkns = state.Tkns();
|
||||
int end = this.Ary_idx();
|
||||
boolean unit_seen = false;
|
||||
for (int i = end - 1; i > -1; i--) { // loop over tokens, moving backward
|
||||
Pxd_itm itm = tkns[i];
|
||||
switch (itm.Tkn_tid()) {
|
||||
case Pxd_itm_.Tid_ws: break; // ignore ws
|
||||
case Pxd_itm_.Tid_unit: unit_seen = true; break; // unit seen; flag
|
||||
case Pxd_itm_.Tid_int:
|
||||
if (unit_seen) { // only if unit seen, reverse int; EX: "1 month ago" effectively becomes "-1 month"
|
||||
Pxd_itm_int itm_int = (Pxd_itm_int)itm;
|
||||
itm_int.Val_(-itm_int.Val());
|
||||
i = -1; // end loop
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
}
|
||||
}
|
||||
class Pxd_itm_day_suffix extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
public Pxd_itm_day_suffix(int ary_idx) {Ctor(ary_idx);}
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_day_suffix;}
|
||||
@Override public int Eval_idx() {return 99;} // set to low priority so it can evaluate after day
|
||||
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_day_suffix(ary_idx);}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
Pxd_itm[] tkn_ary = state.Tkns();
|
||||
int tkn_idx = this.Ary_idx();
|
||||
if (tkn_idx == 0) state.Err_set(Pft_func_time_log.Invalid_day, Bry_fmtr_arg_.int_(Int_.MinValue));
|
||||
Pxd_itm day_itm = tkn_ary[tkn_idx - 1];
|
||||
if (day_itm.Seg_idx() != DateAdp_.SegIdx_day) {
|
||||
state.Err_set(Pft_func_time_log.Invalid_day, Bry_fmtr_arg_.int_(Int_.MinValue));
|
||||
}
|
||||
}
|
||||
public static final Pxd_itm_day_suffix _ = new Pxd_itm_day_suffix(); Pxd_itm_day_suffix() {}
|
||||
}
|
||||
class Pxd_itm_day_relative extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
public Pxd_itm_day_relative(int adj, int ary_idx) {Ctor(ary_idx); this.adj = adj;}
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_day_relative;}
|
||||
@Override public int Eval_idx() {return 5;}
|
||||
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_day_relative(adj, ary_idx);}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
DateAdp date = DateAdp_.Now();
|
||||
if (adj != 0) date = date.Add_day(adj);
|
||||
bldr.Seg_set(DateAdp_.SegIdx_year , date.Year());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_month , date.Month());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_day , date.Day());
|
||||
}
|
||||
|
||||
public static final Pxd_itm_day_relative
|
||||
Today = new Pxd_itm_day_relative(0)
|
||||
, Tomorrow = new Pxd_itm_day_relative(1)
|
||||
, Yesterday = new Pxd_itm_day_relative(-1)
|
||||
;
|
||||
Pxd_itm_day_relative(int adj) {this.adj = adj;} private int adj;
|
||||
}
|
||||
class Pxd_itm_time_relative extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
public Pxd_itm_time_relative(int ary_idx) {Ctor(ary_idx);}
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_time_relative;}
|
||||
@Override public int Eval_idx() {return 5;}
|
||||
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_time_relative(ary_idx);}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
DateAdp date = DateAdp_.Now();
|
||||
bldr.Seg_set(DateAdp_.SegIdx_year , date.Year());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_month , date.Month());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_day , date.Day());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_hour , date.Hour());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_minute , date.Minute());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_second , date.Second());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_frac , date.Frac());
|
||||
}
|
||||
public static final Pxd_itm_time_relative
|
||||
Now = new Pxd_itm_time_relative()
|
||||
;
|
||||
Pxd_itm_time_relative() {}
|
||||
}
|
||||
class Pxd_itm_unit_relative extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
public Pxd_itm_unit_relative(int adj, int ary_idx) {Ctor(ary_idx); this.adj = adj;}
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_unit_relative;}
|
||||
@Override public int Eval_idx() {return 5;}
|
||||
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_unit_relative(adj, ary_idx);}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
Pxd_itm itm = Pxd_itm_.Find_fwd_by_tid(state.Tkns(), this.Ary_idx() + 1, Pxd_itm_.Tid_unit);
|
||||
if (itm == null) state.Err_set(Pft_func_time_log.Invalid_date, Bry_fmtr_arg_.int_(adj));
|
||||
Pxd_itm_unit unit_tkn = (Pxd_itm_unit)itm;
|
||||
unit_tkn.Unit_seg_val_(adj);
|
||||
}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
}
|
||||
public static final Pxd_itm_unit_relative
|
||||
Next = new Pxd_itm_unit_relative(1)
|
||||
, Prev = new Pxd_itm_unit_relative(-1)
|
||||
, This = new Pxd_itm_unit_relative(0)
|
||||
;
|
||||
Pxd_itm_unit_relative(int adj) {this.adj = adj;} private int adj;
|
||||
}
|
||||
class Pxd_itm_unixtime extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
private long unixtime;
|
||||
public Pxd_itm_unixtime(int ary_idx, int seg_idx) {Ctor(ary_idx); Seg_idx_(seg_idx);}
|
||||
public byte[] Name() {return Name_const;} public static final byte[] Name_const = Bry_.new_a7("@");
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_unixtime;}
|
||||
@Override public int Eval_idx() {return 5;} // set to high priority so it can evaluate number early
|
||||
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_unixtime(ary_idx, this.Seg_idx());}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
Pxd_itm[] tkns = state.Tkns();
|
||||
unixtime = Pxd_itm_int_.Read_nearest_as_int_and_skip(state, tkns, this.Ary_idx(), true, Int_.MinValue);
|
||||
}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
DateAdp date = DateAdp_.unixtime_utc_seconds_(unixtime);
|
||||
bldr.Seg_set(DateAdp_.SegIdx_year , date.Year());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_month , date.Month());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_day , date.Day());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_hour , date.Hour());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_minute , date.Minute());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_second , date.Second());
|
||||
bldr.Seg_set(DateAdp_.SegIdx_frac , date.Frac());
|
||||
}
|
||||
}
|
||||
class Pxd_itm_dow_name extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
private int dow_idx;
|
||||
private byte[] dow_name;
|
||||
public Pxd_itm_dow_name(int ary_idx, byte[] dow_name, int dow_idx) {Ctor(ary_idx); this.dow_name = dow_name; this.Seg_idx_(DateAdp_.SegIdx_dayOfWeek); this.dow_idx = dow_idx;}
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_dow_name;}
|
||||
@Override public int Eval_idx() {return 20;}
|
||||
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_dow_name(ary_idx, dow_name, dow_idx);}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {
|
||||
DateAdp now = DateAdp_.Now();
|
||||
int adj = dow_idx - now.DayOfWeek(); // adj = requested_dow - current_dow; EX: requesting Friday, and today is Wednesday; adj = 2 (4 - 2); DATE:2014-05-02
|
||||
if (adj < 0) adj += 7; // requested_down is before current_dow; add 7 to get the next day
|
||||
bldr.Date_(bldr.Date().Add_day(adj));
|
||||
}
|
||||
}
|
||||
class Pxd_itm_iso8601_t extends Pxd_itm_base implements Pxd_itm_prototype {
|
||||
public Pxd_itm_iso8601_t(int ary_idx, int seg_idx) {Ctor(ary_idx); Seg_idx_(seg_idx);}
|
||||
public byte[] Name() {return Name_const;} public static final byte[] Name_const = Bry_.new_a7("T");
|
||||
@Override public byte Tkn_tid() {return Pxd_itm_.Tid_iso8601_t;}
|
||||
@Override public int Eval_idx() {return 99;} // evaluate last
|
||||
public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_iso8601_t(ary_idx, this.Seg_idx());}
|
||||
@Override public void Eval(Pxd_parser state) {
|
||||
Pxd_itm hour = Next_non_ws_tkn(state.Tkns(), this.Ary_idx() + 1);
|
||||
if (hour != null && hour.Seg_idx() == DateAdp_.SegIdx_hour) return; // next item is hour
|
||||
state.Err_set(Pft_func_time_log.Invalid_hour, Bry_fmtr_arg_.bry_("T"));
|
||||
}
|
||||
@Override public void Time_ini(DateAdpBldr bldr) {}
|
||||
private static Pxd_itm Next_non_ws_tkn(Pxd_itm[] tkns, int bgn) {
|
||||
int len = tkns.length;
|
||||
for (int i = bgn; i < len; i++) {
|
||||
Pxd_itm itm = tkns[i];
|
||||
if (itm.Tkn_tid() != Pxd_itm_.Tid_ws) return itm;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
262
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_parser.java
Normal file
262
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_parser.java
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import gplx.core.btries.*;
|
||||
class Pxd_parser {
|
||||
byte[] src; int cur_pos, tkn_bgn_pos, src_len, tkn_type;
|
||||
public Pxd_itm[] Tkns() {return tkns;} Pxd_itm[] tkns;
|
||||
public int Tkns_len() {return tkns_len;} private int tkns_len;
|
||||
public Pxd_itm[] Data_ary() {return data_ary;} Pxd_itm[] data_ary;
|
||||
public int Data_ary_len() {return data_ary_len;} private int data_ary_len;
|
||||
public int Colon_count;
|
||||
public int[] Seg_idxs() {return seg_idxs;} private int[] seg_idxs = new int[DateAdp_.SegIdx__max]; // temp ary for storing current state
|
||||
public boolean Seg_idxs_chk(int... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++)
|
||||
if (ary[i] == Pxd_itm_base.Seg_idx_null) return false;
|
||||
return true;
|
||||
}
|
||||
public void Seg_idxs_(Pxd_itm_int itm, int seg_idx) {Seg_idxs_(itm, seg_idx, itm.Val());}
|
||||
public void Seg_idxs_(Pxd_itm_base itm, int seg_idx, int val) {
|
||||
itm.Seg_idx_(seg_idx);
|
||||
if (seg_idx >= 0) // ignore Seg_idx_null and Seg_idx_skip
|
||||
seg_idxs[seg_idx] = val;
|
||||
}
|
||||
public void Err_set(Gfo_msg_itm itm, Bry_fmtr_arg... args) {
|
||||
if (itm == null) return;
|
||||
Bry_fmtr fmtr = itm.Fmtr();
|
||||
fmtr.Bld_bfr(error_bfr, args);
|
||||
} private Bry_bfr error_bfr = Bry_bfr.new_(32);
|
||||
public DateAdp Parse(byte[] src, Bry_bfr error_bfr) {
|
||||
Tokenize(src); // NOTE: should check if Tokenize failed, but want to be liberal as date parser is not fully implemented; this will always default to 1st day of year; DATE:2014-03-27
|
||||
return Evaluate(src, error_bfr);
|
||||
}
|
||||
private boolean Tokenize(byte[] src) {
|
||||
this.src = src; src_len = src.length;
|
||||
tkns = new Pxd_itm[src_len]; tkns_len = 0;
|
||||
tkn_type = Pxd_itm_.Tid_null; tkn_bgn_pos = -1;
|
||||
cur_pos = 0;
|
||||
Colon_count = 0;
|
||||
error_bfr.Clear();
|
||||
for (int i = 0; i < DateAdp_.SegIdx__max; i++)
|
||||
seg_idxs[i] = Pxd_itm_base.Seg_idx_null;
|
||||
while (cur_pos < src_len) {
|
||||
byte b = src[cur_pos];
|
||||
switch (b) {
|
||||
case Byte_ascii.Space: case Byte_ascii.Tab: case Byte_ascii.Nl:
|
||||
if (tkn_type != Pxd_itm_.Tid_ws) MakePrvTkn(cur_pos, Pxd_itm_.Tid_ws); break; // SEE:NOTE_1 for logic
|
||||
case Byte_ascii.Dash: case Byte_ascii.Dot: case Byte_ascii.Colon: case Byte_ascii.Slash:
|
||||
if (tkn_type != b) MakePrvTkn(cur_pos, b); break;
|
||||
case Byte_ascii.Num_0: case Byte_ascii.Num_1: case Byte_ascii.Num_2: case Byte_ascii.Num_3: case Byte_ascii.Num_4:
|
||||
case Byte_ascii.Num_5: case Byte_ascii.Num_6: case Byte_ascii.Num_7: case Byte_ascii.Num_8: case Byte_ascii.Num_9:
|
||||
if (tkn_type != Pxd_itm_.Tid_int) MakePrvTkn(cur_pos, Pxd_itm_.Tid_int); break;
|
||||
case Byte_ascii.Ltr_A: case Byte_ascii.Ltr_B: case Byte_ascii.Ltr_C: case Byte_ascii.Ltr_D: case Byte_ascii.Ltr_E:
|
||||
case Byte_ascii.Ltr_F: case Byte_ascii.Ltr_G: case Byte_ascii.Ltr_H: case Byte_ascii.Ltr_I: case Byte_ascii.Ltr_J:
|
||||
case Byte_ascii.Ltr_K: case Byte_ascii.Ltr_L: case Byte_ascii.Ltr_M: case Byte_ascii.Ltr_N: case Byte_ascii.Ltr_O:
|
||||
case Byte_ascii.Ltr_P: case Byte_ascii.Ltr_Q: case Byte_ascii.Ltr_R: case Byte_ascii.Ltr_S: case Byte_ascii.Ltr_T:
|
||||
case Byte_ascii.Ltr_U: case Byte_ascii.Ltr_V: case Byte_ascii.Ltr_W: case Byte_ascii.Ltr_X: case Byte_ascii.Ltr_Y: case Byte_ascii.Ltr_Z:
|
||||
case Byte_ascii.Ltr_a: case Byte_ascii.Ltr_b: case Byte_ascii.Ltr_c: case Byte_ascii.Ltr_d: case Byte_ascii.Ltr_e:
|
||||
case Byte_ascii.Ltr_f: case Byte_ascii.Ltr_g: case Byte_ascii.Ltr_h: case Byte_ascii.Ltr_i: case Byte_ascii.Ltr_j:
|
||||
case Byte_ascii.Ltr_k: case Byte_ascii.Ltr_l: case Byte_ascii.Ltr_m: case Byte_ascii.Ltr_n: case Byte_ascii.Ltr_o:
|
||||
case Byte_ascii.Ltr_p: case Byte_ascii.Ltr_q: case Byte_ascii.Ltr_r: case Byte_ascii.Ltr_s: case Byte_ascii.Ltr_t:
|
||||
case Byte_ascii.Ltr_u: case Byte_ascii.Ltr_v: case Byte_ascii.Ltr_w: case Byte_ascii.Ltr_x: case Byte_ascii.Ltr_y: case Byte_ascii.Ltr_z:
|
||||
case Byte_ascii.At:
|
||||
MakePrvTkn(cur_pos, Pxd_itm_.Tid_null); // first, make prv tkn
|
||||
Object o = trie.Match_bgn_w_byte(b, src, cur_pos, src_len); // now match String against tkn
|
||||
if (o == null) return false; // unknown letter / word; exit now;
|
||||
tkns[tkns_len] = ((Pxd_itm_prototype)o).MakeNew(tkns_len);
|
||||
++tkns_len;
|
||||
cur_pos = trie.Match_pos() - 1; // -1 b/c trie matches to next char, and ++ below
|
||||
break;
|
||||
case Byte_ascii.Comma: case Byte_ascii.Plus:
|
||||
MakePrvTkn(cur_pos, Pxd_itm_.Tid_null);
|
||||
tkns[tkns_len] = new Pxd_itm_sym(tkns_len, b);
|
||||
++tkns_len;
|
||||
break;
|
||||
}
|
||||
++cur_pos;
|
||||
}
|
||||
MakePrvTkn(cur_pos, Pxd_itm_.Tid_null);
|
||||
return true;
|
||||
}
|
||||
private void MakePrvTkn(int cur_pos, int nxt_type) {
|
||||
Pxd_itm itm = null;
|
||||
switch (tkn_type) {
|
||||
case Pxd_itm_.Tid_int:
|
||||
int int_val = Bry_.Xto_int_or(src, tkn_bgn_pos, cur_pos, Int_.MinValue);
|
||||
if (int_val == Int_.MinValue) {} // FUTURE: warn
|
||||
int digits = cur_pos - tkn_bgn_pos;
|
||||
switch (digits) {
|
||||
case 14:
|
||||
case 8:
|
||||
itm = new Pxd_itm_int_dmy_14(tkns_len, Bry_.Mid(src, tkn_bgn_pos, cur_pos), digits); break;
|
||||
case 6:
|
||||
itm = new Pxd_itm_int_mhs_6(tkns_len, Bry_.Mid(src, tkn_bgn_pos, cur_pos)); break;
|
||||
default:
|
||||
itm = new Pxd_itm_int(tkns_len, digits, int_val); break;
|
||||
}
|
||||
break;
|
||||
case Pxd_itm_.Tid_ws: itm = new Pxd_itm_ws(tkns_len); break;
|
||||
case Pxd_itm_.Tid_dash: itm = new Pxd_itm_dash(tkns_len); break;
|
||||
case Pxd_itm_.Tid_dot: itm = new Pxd_itm_dot(tkns_len); break;
|
||||
case Pxd_itm_.Tid_colon: itm = new Pxd_itm_colon(tkns_len); break;
|
||||
case Pxd_itm_.Tid_slash: itm = new Pxd_itm_slash(tkns_len); break;
|
||||
case Pxd_itm_.Tid_null: break; // NOOP
|
||||
}
|
||||
if (itm != null) {
|
||||
tkns[tkns_len] = itm;
|
||||
++tkns_len;
|
||||
}
|
||||
tkn_type = nxt_type;
|
||||
tkn_bgn_pos = cur_pos;
|
||||
}
|
||||
DateAdp Evaluate(byte[] src, Bry_bfr error) {
|
||||
if (tkns_len == 0) {
|
||||
Err_set(Pft_func_time_log.Invalid_day, Bry_fmtr_arg_.bry_(src));
|
||||
return null;
|
||||
}
|
||||
Pxd_itm[] eval_ary = Pxd_itm_sorter.XtoAryAndSort(tkns, tkns_len);
|
||||
MakeDataAry();
|
||||
for (int i = 0; i < tkns_len; i++) {
|
||||
eval_ary[i].Eval(this);
|
||||
if (error_bfr.Len() != 0) {
|
||||
error.Add_bfr_and_clear(error_bfr);
|
||||
return DateAdp_.MinValue;
|
||||
}
|
||||
}
|
||||
DateAdpBldr bldr = new DateAdpBldr(DateAdp_.Now().Year(), 1, 1, 0, 0, 0, 0);
|
||||
for (int i = 0; i < tkns_len; i++) {
|
||||
Pxd_itm itm = (Pxd_itm)tkns[i];
|
||||
itm.Time_ini(bldr);
|
||||
}
|
||||
return bldr.Bld();
|
||||
}
|
||||
private void MakeDataAry() {
|
||||
data_ary = new Pxd_itm[tkns_len]; data_ary_len = 0;
|
||||
for (int i = 0; i < tkns_len; i++) {
|
||||
Pxd_itm itm = tkns[i];
|
||||
switch (itm.Tkn_tid()) {
|
||||
case Pxd_itm_.Tid_month_name:
|
||||
case Pxd_itm_.Tid_int:
|
||||
itm.Data_idx_(data_ary_len);
|
||||
data_ary[data_ary_len++] = itm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static Btrie_slim_mgr trie = Pxd_parser_.Trie();
|
||||
}
|
||||
class Pxd_parser_ {
|
||||
public static Btrie_slim_mgr Trie() {
|
||||
if (trie == null) {
|
||||
trie = Btrie_slim_mgr.ci_ascii_(); // NOTE:ci.ascii:MW_const.en
|
||||
Init();
|
||||
}
|
||||
return trie;
|
||||
} static Btrie_slim_mgr trie;
|
||||
private static final String[] Names_month_full = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"};
|
||||
private static final String[] Names_month_abrv = {"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"};
|
||||
private static final String[] Names_month_roman = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"};
|
||||
private static final String[] Names_day_suffix = {"st", "nd", "rd", "th"};
|
||||
private static final String[] Names_day_full = {"sunday", "monday", "tuesday", "wednesday" , "thursday", "friday", "saturday"};
|
||||
private static final String[] Names_day_abrv = {"sun", "mon", "tue", "wed" , "thu", "fri", "sat"};
|
||||
//TODO:
|
||||
//private static final String[] Names_day_text = {"weekday", "weekdays"};
|
||||
//private static final String[] Names_ordinal_num = {"first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth"};
|
||||
|
||||
private static void Init_unit(int seg_idx, String... name_ary) {Init_unit(seg_idx, 1, name_ary);}
|
||||
private static void Init_unit(int seg_idx, int seg_val, String... name_ary) {
|
||||
int name_ary_len = name_ary.length;
|
||||
for (int i = 0; i < name_ary_len; i++) {
|
||||
byte[] name_bry = Bry_.new_u8(name_ary[i]);
|
||||
trie.Add_obj(name_bry, new Pxd_itm_unit(-1, name_bry, seg_idx, seg_val));
|
||||
}
|
||||
}
|
||||
public static final byte[]
|
||||
Unit_name_month = Bry_.new_a7("month")
|
||||
, Unit_name_day = Bry_.new_a7("day")
|
||||
, Unit_name_hour = Bry_.new_a7("hour")
|
||||
;
|
||||
private static void Init() {
|
||||
Init_reg_months(Names_month_full);
|
||||
Init_reg_months(Names_month_abrv);
|
||||
Init_reg_months(Names_month_roman);
|
||||
Init_reg_month("sept", 9);
|
||||
Init_reg_days_of_week(Names_day_full);
|
||||
Init_reg_days_of_week(Names_day_abrv);
|
||||
Init_unit(DateAdp_.SegIdx_second , "sec", "secs", "second", "seconds");
|
||||
Init_unit(DateAdp_.SegIdx_minute , "min", "mins", "minute", "minutes");
|
||||
Init_unit(DateAdp_.SegIdx_hour , "hour", "hours");
|
||||
Init_unit(DateAdp_.SegIdx_day , "day", "days");
|
||||
Init_unit(DateAdp_.SegIdx_day, 14 , "fortnight", "forthnight");
|
||||
Init_unit(DateAdp_.SegIdx_month , "month", "months");
|
||||
Init_unit(DateAdp_.SegIdx_year , "year", "years");
|
||||
Init_unit(DateAdp_.SegIdx_day, 7 , "week", "weeks");
|
||||
trie.Add_obj(Pxd_itm_ago.Name_ago, new Pxd_itm_ago(-1, -1));
|
||||
Init_suffix(Names_day_suffix);
|
||||
Init_relative();
|
||||
trie.Add_obj(Pxd_itm_unixtime.Name_const, new Pxd_itm_unixtime(-1, -1));
|
||||
trie.Add_obj(Pxd_itm_iso8601_t.Name_const, new Pxd_itm_iso8601_t(-1, -1));
|
||||
}
|
||||
private static void Init_reg_months(String[] names) {
|
||||
for (int i = 0; i < names.length; i++)
|
||||
Init_reg_month(names[i], i + Int_.Base1); // NOTE: Months are Base1: 1-12
|
||||
}
|
||||
private static void Init_reg_month(String name_str, int seg_val) {
|
||||
byte[] name_ary = Bry_.new_u8(name_str);
|
||||
trie.Add_obj(name_ary, new Pxd_itm_month_name(-1, name_ary, DateAdp_.SegIdx_month, seg_val));
|
||||
}
|
||||
private static void Init_reg_days_of_week(String[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
byte[] itm_bry = Bry_.new_u8(ary[i]);
|
||||
trie.Add_obj(itm_bry, new Pxd_itm_dow_name(-1, itm_bry, i)); // NOTE: days are base0; 0-6
|
||||
}
|
||||
}
|
||||
private static void Init_suffix(String[] suffix_ary) {
|
||||
int len = suffix_ary.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
String suffix = suffix_ary[i];
|
||||
trie.Add_obj(suffix, Pxd_itm_day_suffix._);
|
||||
}
|
||||
}
|
||||
private static void Init_relative() {
|
||||
trie.Add_obj("today", Pxd_itm_day_relative.Today);
|
||||
trie.Add_obj("tomorrow", Pxd_itm_day_relative.Tomorrow);
|
||||
trie.Add_obj("yesterday", Pxd_itm_day_relative.Yesterday);
|
||||
trie.Add_obj("now", Pxd_itm_time_relative.Now);
|
||||
trie.Add_obj("next", Pxd_itm_unit_relative.Next);
|
||||
trie.Add_obj("last", Pxd_itm_unit_relative.Prev);
|
||||
trie.Add_obj("previous", Pxd_itm_unit_relative.Prev);
|
||||
trie.Add_obj("this", Pxd_itm_unit_relative.This);
|
||||
}
|
||||
}
|
||||
/*
|
||||
NOTE_1:parsing works by completing previous items and then setting current;
|
||||
EX: "123 456"
|
||||
1: tkn_type = null; b = number
|
||||
complete tkn (note that tkn is null)
|
||||
set tkn_type to number; set tkn_bgn to 0
|
||||
2: b == number == tkn_type; noop
|
||||
3: b == number == tkn_type; noop
|
||||
4: b == space != tkn_type;
|
||||
complete prv
|
||||
create tkn with bgn = tkn_bgn and end = cur_pos
|
||||
set tkn_type to space; set tkn_bgn to cur_pos
|
||||
etc..
|
||||
*/
|
||||
95
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_parser_tst.java
Normal file
95
400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_parser_tst.java
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*;
|
||||
import org.junit.*;
|
||||
public class Pxd_parser_tst {
|
||||
Bry_bfr bfr = Bry_bfr.new_(16); Pxd_parser parser = new Pxd_parser();
|
||||
@Before public void init() {Tfds.Now_enabled_y_(); Tfds.Now_set(test_date);} DateAdp test_date = DateAdp_.parse_fmt("2012-02-27", "yyyy-MM-dd");
|
||||
@After public void teardown() {Tfds.Now_enabled_n_();}
|
||||
@Test public void Month_name_0__day__year() {tst_date_("Mar 2 2001" , "2001-03-02");} // y:Mar-02-2001;Mar.02.2001;Mar 02, 2001 n:Mar/02/2001;Feb,05,2011
|
||||
@Test public void Month_name_0__day__year__bad_day() {tst_date_("Mar 32 2001" , "Invalid day: 32");}
|
||||
@Test public void Month_name_0__day__year__bad_year() {tst_date_("Mar 3 999" , "0999-03-03");}
|
||||
@Test public void Month_name_0__day__year__bad_day_year() {tst_date_("Mar 32 999" , "Invalid day: 32");}
|
||||
@Test public void Month_name_0__year() {tst_date_("Mar 2001" , "2001-03-01");}
|
||||
@Test public void Month_name_0__day() {tst_date_("Mar 02" , "2012-03-02");}
|
||||
@Test public void Month_name_0__day_fail() {tst_date_("Mar 32" , "Invalid day: 32");}
|
||||
@Test public void Month_name_0() {tst_date_("Mar" , "2012-03-01");} // y: ,.,.. Feb; n: / Feb, - Feb
|
||||
@Test public void Month_name_1__day__year() {tst_date_("2 Mar 2001" , "2001-03-02");} // y: 3-Feb-2012; 3 Feb 2012;
|
||||
@Test public void Month_name_1__year__day() {tst_date_("2001 Mar 02" , "2001-03-02");} // y: 2012-Feb-3 n:2012.Feb.3;2012 Feb 3; 2012,Feb,3;2012/Feb/3
|
||||
@Test public void Month_name_1__day__year__guess() {tst_date_("02 Mar 01" , "2001-03-02");}
|
||||
@Test public void Month_name_1__day() {tst_date_("02 Mar" , "2012-03-02");}
|
||||
@Test public void Month_name_1__year() {tst_date_("2003 Mar" , "2003-03-01");}
|
||||
@Test public void Month_name_2__day__year() {tst_date_("2001.02.Mar" , "2001-03-02");} // y: 2012.5.Feb; 2012 5 Feb n: 2012-5-Feb; 2012/5/Feb
|
||||
@Test public void Year_0__month__day() {tst_date_("2001-03-31" , "2001-03-31");}
|
||||
@Test public void Year_0__day__month__fail() {tst_date_("2001-31-03" , "Invalid month: 31");} // n:2012.31.03; 2012/31/03
|
||||
@Test public void Year_0__month() {tst_date_("2001-03" , "2001-03-01");}
|
||||
@Test public void Year_0() {tst_date_("2001" , "2001-01-01");}
|
||||
@Test public void Year_1() {tst_date_("31-2001" , "Invalid date: 4 digit year must be either yyyy-##-## or ##-##-yyyy");} // n:31-2012; 31.2012; 31/2012; 03-2012; 03.2012; 03/2012
|
||||
@Test public void Year_2__month__day() {tst_date_("03/31/2001" , "2001-03-31");} // n: 03.31.2012;03-31-2012
|
||||
@Test public void Year_2__day__month() {tst_date_("31-03-2001" , "2001-03-31");} // y: 31.03.2012; n:31/03/2012
|
||||
@Test public void Day_0__month__day() {tst_date_("31-03-02" , "2031-03-02");}
|
||||
@Test public void Day_0__month__day_dot() {tst_date_("22.05.70" , "1970-05-22");} // PURPOSE: dmy when delimiter is dot
|
||||
@Test public void Day_1__month__year() {tst_date_("03-31-02" , "2002-03-31");}
|
||||
@Test public void Day_2__month__day() {tst_date_("03-02-31" , "2031-03-02");}
|
||||
@Test public void Dmy_is_default() {tst_date_("03-04-05" , "2005-04-03");}
|
||||
@Test public void Dmy_is_default_y4() {tst_date_("2-5-2000" , "2000-05-02");}
|
||||
@Test public void Colon_hour_min() {tst_time_("01:02" , "01:02:00.000");}
|
||||
@Test public void Colon_hour_min_second() {tst_time_("01:02:03" , "01:02:03.000");}
|
||||
@Test public void Time_all() {tst_both_("04-03-05 06:07:08" , "2005-03-04 06:07:08.000");}
|
||||
@Test public void Unit_day_pos() {tst_date_("+ 3 days" , "2012-03-01");}
|
||||
@Test public void Unit_day_neg() {tst_date_("- 3 days" , "2012-02-24");}
|
||||
@Test public void Unit_day_neg_w_day() {tst_date_("30 May 2012 -1 days" , "2012-05-29");} // PAGE:en.w:Main Page
|
||||
@Test public void Unit_week() {tst_date_("- 1 week" , "2012-02-26");} // PURPOSE.FIX: "week" was not being handled; error on main Page; EX:da.wikipedia.org/Main_Page
|
||||
@Test public void Time_len_6() {tst_time_("041526" , "04:15:26.000");}
|
||||
@Test public void Err_one_num() {tst_time_("2" , "Invalid year: 2");} // occurs on some templates; PAGE:en.w:Voyager 1 and {{date}}
|
||||
@Test public void Dmy_at_y_dot() {tst_date_("1.2.70" , "1970-02-01");} // PURPOSE: dmy when delimiter is dot
|
||||
@Test public void Mdy_at_y_slash() {tst_date_("1/2/70" , "1970-01-02");} // PURPOSE: mdy when delimiter is slash
|
||||
@Test public void Ago() {tst_date_("1 month ago" , "2012-01-27");}
|
||||
|
||||
private void tst_date_(String raw, String expd) {
|
||||
byte[] raw_ary = Bry_.new_u8(raw);
|
||||
DateAdp date = parser.Parse(raw_ary, bfr);
|
||||
if (date == DateAdp_.MinValue)
|
||||
Tfds.Eq(expd, bfr.Xto_str_and_clear(), raw);
|
||||
else
|
||||
Tfds.Eq(expd, date.XtoStr_fmt_yyyy_MM_dd());
|
||||
}
|
||||
private void tst_time_(String raw, String expd) {
|
||||
byte[] raw_ary = Bry_.new_u8(raw);
|
||||
DateAdp date = parser.Parse(raw_ary, bfr);
|
||||
if (date == DateAdp_.MinValue)
|
||||
Tfds.Eq(expd, bfr.Xto_str_and_clear(), raw);
|
||||
else
|
||||
Tfds.Eq(expd, date.XtoStr_fmt("HH:mm:ss.fff"));
|
||||
}
|
||||
private void tst_both_(String raw, String expd) {
|
||||
byte[] raw_ary = Bry_.new_u8(raw);
|
||||
DateAdp date = parser.Parse(raw_ary, bfr);
|
||||
if (date == DateAdp_.MinValue)
|
||||
Tfds.Eq(expd, bfr.Xto_str_and_clear(), raw);
|
||||
else
|
||||
Tfds.Eq(expd, date.XtoStr_fmt("yyyy-MM-dd HH:mm:ss.fff"));
|
||||
}
|
||||
}
|
||||
/*
|
||||
12:12 2012 5 Feb: pass
|
||||
2012 5 Feb 12:12: fail
|
||||
2012-Feb-5 12:12: pass (but 2012-02-01)
|
||||
2012-Feb-05 12:12: pass (and 2012-02-05)
|
||||
{{#time:Y-m-d H:i:s A|.....2012.-.-.Feb-09....}}
|
||||
*/
|
||||
Reference in New Issue
Block a user