From 2e5994788f1aa519ec29d6caa48715277ee1a651 Mon Sep 17 00:00:00 2001 From: gnosygnu Date: Sun, 18 Nov 2018 23:04:59 -0500 Subject: [PATCH] ParserFunctions: Support next / previous for day of week [#262] --- .../times/Pft_func_time__basic__tst.java | 12 ++- .../xowa/xtns/pfuncs/times/Pxd_date_bldr.java | 36 +++++++++ .../gplx/xowa/xtns/pfuncs/times/Pxd_itm_.java | 40 +++------- .../xtns/pfuncs/times/Pxd_itm_dow_name.java | 55 ++++++++++++++ .../xowa/xtns/pfuncs/times/Pxd_itm_int.java | 13 ++-- .../xowa/xtns/pfuncs/times/Pxd_itm_misc.java | 6 +- .../xtns/pfuncs/times/Pxd_itm_month_name.java | 73 +++++-------------- .../pfuncs/times/Pxd_itm_unit_relative.java | 62 ++++++++++++++++ .../xowa/xtns/pfuncs/times/Pxd_parser.java | 6 +- 9 files changed, 207 insertions(+), 96 deletions(-) create mode 100644 400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_date_bldr.java create mode 100644 400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_dow_name.java create mode 100644 400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_unit_relative.java diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_func_time__basic__tst.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_func_time__basic__tst.java index 2a122d360..62742a4d6 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_func_time__basic__tst.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pft_func_time__basic__tst.java @@ -66,10 +66,20 @@ public class Pft_func_time__basic__tst { @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_month_next() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|next month}}" , "2012-02-02");} + @Test public void Unit_rel_month_prev() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|previous month}}" , "2011-12-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 Datetime_now.Get() 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_monday_none() {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_monday_this() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|this Monday}}" , "2012-01-02");} // "this Monday" is same as "Monday" + @Test public void Day_monday_next() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|next Monday}}" , "2012-01-09");} + @Test public void Day_monday_prev() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|previous Monday}}" , "2011-12-26");} + @Test public void Day_sunday_none() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|Sunday}}" , "2012-01-08");} + @Test public void Day_sunday_this() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|this Sunday}}" , "2012-01-08");} + @Test public void Day_sunday_next() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|next Sunday}}" , "2012-01-15");} + @Test public void Day_sunday_prev() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|previous Sunday}}" , "2012-01-01");} + @Test public void Day_relative_smoke() {fxt.Test_parse_tmpl_str("{{#time:Y-m-d|6 april next sunday}}" , "2012-04-15");} @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");} diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_date_bldr.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_date_bldr.java new file mode 100644 index 000000000..41195c8b0 --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_date_bldr.java @@ -0,0 +1,36 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*; +public class Pxd_date_bldr { + private int[] seg_ary; + public Pxd_date_bldr(int year, int month, int day, int hour, int minute, int second, int frac) { + this.seg_ary = new int[] {year, month, day, hour, minute, second, frac}; + } + + // most workers will just set individual segments + public void Seg_set(int idx, int val) { + seg_ary[idx] = val; + } + + // relative workers will convert segs to date, add a relative unit, and then convert back to date + // note that the date conversion is necessary b/c Date class has logic to do things like "2017-12-31 +1 day" and rollover to next month / next year + public DateAdp To_date() { + return DateAdp_.seg_(seg_ary); + } + public void By_date(DateAdp v) { + this.seg_ary = v.XtoSegAry(); + } +} diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_.java index dd101e468..4f8415fe8 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_.java @@ -22,7 +22,7 @@ interface Pxd_itm { int Eval_idx(); int Data_idx(); void Data_idx_(int v); boolean Eval(Pxd_parser state); - boolean Time_ini(DateAdpBldr bldr); + boolean Time_ini(Pxd_date_bldr bldr); } class Pxd_itm_ { public static final int @@ -46,7 +46,16 @@ class Pxd_itm_ { , Tid_colon = Byte_ascii.Colon , Tid_ws = 98 , Tid_sym = 99 - ; + ; + + public static Pxd_itm Find_fwd__non_ws(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() != Tid_ws) return itm; + } + return null; + } 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]; @@ -73,38 +82,13 @@ abstract class Pxd_itm_base implements Pxd_itm { 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 boolean Eval(Pxd_parser state) {return true;} - @gplx.Virtual public boolean Time_ini(DateAdpBldr bldr) {return true;} + @gplx.Virtual public boolean Time_ini(Pxd_date_bldr bldr) {return true;} 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 Datetime_now.Get(); // not dirtied; default to now; - } - public DateAdpBldr Date_(DateAdp v) {date = v; return this;} DateAdp date = null; - public void 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; - } - 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 diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_dow_name.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_dow_name.java new file mode 100644 index 000000000..f850d77e8 --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_dow_name.java @@ -0,0 +1,55 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*; +class Pxd_itm_dow_name extends Pxd_itm_base implements Pxd_itm_prototype { + private final int dow_idx; + private final byte[] dow_name; + private int relative_adj = Int_.Max_value; + public Pxd_itm_dow_name(int ary_idx, byte[] dow_name, int dow_idx) { + this.dow_name = dow_name; + this.dow_idx = dow_idx; + this.Ctor(ary_idx); + this.Seg_idx_(DateAdp_.SegIdx_dayOfWeek); + } + @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);} + public void Relative_adj_(int v) { // handled by relative_word; EX: "next tuesday" + this.relative_adj = v; + } + @Override public boolean Eval(Pxd_parser state) {return true;} + @Override public boolean Time_ini(Pxd_date_bldr bldr) { + DateAdp cur = bldr.To_date(); + int cur_dow = cur.DayOfWeek(); + + // adj = requested_dow - cur_dow; EX: requesting Friday, and today is Wednesday; adj = 2 (4 - 2); DATE:2014-05-02 + int adj = dow_idx - cur.DayOfWeek(); + + // requested_dow is before cur_dow; add 7 to get the next day + if (adj < 0) adj += 7; + + // "next" always adds 7 days + if (relative_adj == 1) + adj += 7; + // "previous" always subtracts 7 days; + else if (relative_adj == -1) + adj -= 7; + + cur = cur.Add_day(adj); + bldr.By_date(cur); + return true; + } +} diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_int.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_int.java index bebd7f88f..612033568 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_int.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_int.java @@ -41,27 +41,28 @@ class Pxd_itm_int extends Pxd_itm_base implements Pxd_itm_int_interface { 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 boolean Time_ini(DateAdpBldr bldr) { + @Override public boolean Time_ini(Pxd_date_bldr bldr) { int seg_idx = this.Seg_idx(); if (seg_idx == Pxd_itm_base.Seg_idx_skip) return true; if (val_is_adj) { if (val == 0) return true; // no adjustment to make - DateAdp date = bldr.Date(); + DateAdp date = bldr.To_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 true; } - bldr.Date_(date); + bldr.By_date(date); } else { if (val == 0) { // 0 means subtract 1; EX:w:Mariyinsky_Palace; DATE:2014-03-25 - DateAdp date = bldr.Date(); + DateAdp date = bldr.To_date(); switch (seg_idx) { - case DateAdp_.SegIdx_month: date = DateAdp_.seg_(new int[] {date.Year(), 1, date.Day(), date.Hour(), date.Minute(), date.Second(), date.Frac()}).Add_month(-1); bldr.Date_(date); break; - case DateAdp_.SegIdx_day: date = DateAdp_.seg_(new int[] {date.Year(), date.Month(), 1, date.Hour(), date.Minute(), date.Second(), date.Frac()}).Add_day(-1); bldr.Date_(date); break; + case DateAdp_.SegIdx_month: date = DateAdp_.seg_(new int[] {date.Year(), 1, date.Day(), date.Hour(), date.Minute(), date.Second(), date.Frac()}).Add_month(-1); break; + case DateAdp_.SegIdx_day: date = DateAdp_.seg_(new int[] {date.Year(), date.Month(), 1, date.Hour(), date.Minute(), date.Second(), date.Frac()}).Add_day(-1); break; default: return true; } + bldr.By_date(date); } else { if (seg_idx == -1) return false; // PAGE:New_York_City EX: March 14, 2,013; DATE:2016-07-06 diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_misc.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_misc.java index faf744aa2..1ebeb1c87 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_misc.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_misc.java @@ -79,7 +79,7 @@ class Pxd_itm_slash extends Pxd_itm_base { 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 boolean Time_ini(DateAdpBldr bldr) {return true;} + @Override public boolean Time_ini(Pxd_date_bldr bldr) {return true;} 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;} } @@ -88,7 +88,7 @@ class Pxd_itm_int_dmy_14 extends Pxd_itm_base implements Pxd_itm_int_interface { public int Xto_int_or(int or) {return Bry_.To_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 boolean Time_ini(DateAdpBldr bldr) { + @Override public boolean Time_ini(Pxd_date_bldr bldr) { if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return true; // has seg_idx; already eval'd by something else bldr.Seg_set(DateAdp_.SegIdx_year , Bry_.To_int_or(src, 0, 4, 0)); bldr.Seg_set(DateAdp_.SegIdx_month , Bry_.To_int_or(src, 4, 6, 0)); @@ -111,7 +111,7 @@ class Pxd_itm_int_mhs_6 extends Pxd_itm_base implements Pxd_itm_int_interface { public int Xto_int_or(int or) {return Bry_.To_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 boolean Time_ini(DateAdpBldr bldr) { + @Override public boolean Time_ini(Pxd_date_bldr bldr) { if (this.Seg_idx() != Pxd_itm_base.Seg_idx_null) return true; // has seg_idx; already eval'd by something else bldr.Seg_set(DateAdp_.SegIdx_hour , Bry_.To_int_or(src, 0, 2, 0)); bldr.Seg_set(DateAdp_.SegIdx_minute , Bry_.To_int_or(src, 2, 4, 0)); diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_month_name.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_month_name.java index bd62eef1f..0ce298e58 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_month_name.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_month_name.java @@ -16,10 +16,16 @@ Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*; import gplx.core.brys.*; 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; + private byte[] name; + private int seg_val; + 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; + } @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; @@ -142,7 +148,7 @@ class Pxd_itm_month_name extends Pxd_itm_base implements Pxd_itm_prototype { } } } - @Override public boolean Time_ini(DateAdpBldr bldr) { + @Override public boolean Time_ini(Pxd_date_bldr bldr) { bldr.Seg_set(this.Seg_idx(), seg_val); return true; } @@ -202,9 +208,8 @@ class Pxd_itm_unit extends Pxd_itm_base implements Pxd_itm_prototype { } return true; } - @Override public boolean Time_ini(DateAdpBldr bldr) { - DateAdp cur = bldr.Date(); - if (cur == null) cur = Datetime_now.Get(); + @Override public boolean Time_ini(Pxd_date_bldr bldr) { + DateAdp cur = bldr.To_date(); int val = seg_val * seg_multiple; switch (this.Seg_idx()) { case DateAdp_.SegIdx_second: cur = cur.Add_second(val); break; @@ -215,7 +220,7 @@ class Pxd_itm_unit extends Pxd_itm_base implements Pxd_itm_prototype { case DateAdp_.SegIdx_year : cur = cur.Add_year (val); break; default: throw Err_.new_unhandled(this.Seg_idx()); } - bldr.Date_(cur); + bldr.By_date(cur); return true; } } @@ -246,7 +251,7 @@ class Pxd_itm_ago extends Pxd_itm_base implements Pxd_itm_prototype { } return true; } - @Override public boolean Time_ini(DateAdpBldr bldr) {return true;} + @Override public boolean Time_ini(Pxd_date_bldr bldr) {return true;} } class Pxd_itm_day_suffix extends Pxd_itm_base implements Pxd_itm_prototype { public Pxd_itm_day_suffix(int ary_idx) {Ctor(ary_idx);} @@ -271,7 +276,7 @@ class Pxd_itm_day_relative extends Pxd_itm_base implements Pxd_itm_prototype { @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 boolean Eval(Pxd_parser state) {return true;} - @Override public boolean Time_ini(DateAdpBldr bldr) { + @Override public boolean Time_ini(Pxd_date_bldr bldr) { DateAdp date = Datetime_now.Get(); if (adj != 0) date = date.Add_day(adj); bldr.Seg_set(DateAdp_.SegIdx_year , date.Year()); @@ -293,7 +298,7 @@ class Pxd_itm_time_relative extends Pxd_itm_base implements Pxd_itm_prototype { @Override public int Eval_idx() {return 5;} public Pxd_itm MakeNew(int ary_idx) {return new Pxd_itm_time_relative(ary_idx);} @Override public boolean Eval(Pxd_parser state) {return true;} - @Override public boolean Time_ini(DateAdpBldr bldr) { + @Override public boolean Time_ini(Pxd_date_bldr bldr) { DateAdp date = Datetime_now.Get(); bldr.Seg_set(DateAdp_.SegIdx_year , date.Year()); bldr.Seg_set(DateAdp_.SegIdx_month , date.Month()); @@ -309,34 +314,6 @@ class Pxd_itm_time_relative extends Pxd_itm_base implements Pxd_itm_prototype { ; Pxd_itm_time_relative() {} } -class Pxd_itm_unit_relative extends Pxd_itm_base implements Pxd_itm_prototype { // EX: "next year" - private final int adj; - 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 boolean Eval(Pxd_parser state) { - // find next token: EX: sec, hour, day, fortnight, month, etc. - 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, Bfr_arg_.New_int(adj)); - - // cast to unit; may fail; EX:update in "last update" as per "March 2006 [last update]";PAGE:s.w:Synesthesia;DATE:2016-07-06 - Pxd_itm_unit unit_tkn = (Pxd_itm_unit)itm; - if (unit_tkn == null) {state.Err_set(Pft_func_time_log.Invalid_date, Bfr_arg_.New_int(adj)); return false;} - - unit_tkn.Unit_seg_val_(adj); - return true; - } - @Override public boolean Time_ini(DateAdpBldr bldr) {return true;} - public static final Pxd_itm_unit_relative - Next = new Pxd_itm_unit_relative( 1, 0) - , Prev = new Pxd_itm_unit_relative(-1, 0) - , This = new Pxd_itm_unit_relative( 0, 0) - ; -} 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);} @@ -349,7 +326,7 @@ class Pxd_itm_unixtime extends Pxd_itm_base implements Pxd_itm_prototype { unixtime = Pxd_itm_int_.Read_nearest_as_int_and_skip(state, tkns, this.Ary_idx(), true, Int_.Min_value); return true; } - @Override public boolean Time_ini(DateAdpBldr bldr) { + @Override public boolean Time_ini(Pxd_date_bldr bldr) { DateAdp date = DateAdp_.unixtime_utc_seconds_(unixtime); bldr.Seg_set(DateAdp_.SegIdx_year , date.Year()); bldr.Seg_set(DateAdp_.SegIdx_month , date.Month()); @@ -361,22 +338,6 @@ class Pxd_itm_unixtime extends Pxd_itm_base implements Pxd_itm_prototype { return true; } } -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 boolean Eval(Pxd_parser state) {return true;} - @Override public boolean Time_ini(DateAdpBldr bldr) { - DateAdp now = Datetime_now.Get(); - 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)); - return true; - } -} 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"); @@ -389,7 +350,7 @@ class Pxd_itm_iso8601_t extends Pxd_itm_base implements Pxd_itm_prototype { state.Err_set(Pft_func_time_log.Invalid_hour, Bfr_arg_.New_bry("T")); return true; } - @Override public boolean Time_ini(DateAdpBldr bldr) {return true;} + @Override public boolean Time_ini(Pxd_date_bldr bldr) {return true;} private static Pxd_itm Next_non_ws_tkn(Pxd_itm[] tkns, int bgn) { int len = tkns.length; for (int i = bgn; i < len; i++) { diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_unit_relative.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_unit_relative.java new file mode 100644 index 000000000..b75606d11 --- /dev/null +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_itm_unit_relative.java @@ -0,0 +1,62 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012-2017 gnosygnu@gmail.com + +XOWA is licensed under the terms of the General Public License (GPL) Version 3, +or alternatively under the terms of the Apache License Version 2.0. + +You may use XOWA according to either of these licenses as is most appropriate +for your project on a case-by-case basis. + +The terms of each license can be found in the source code repository: + +GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt +Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt +*/ +package gplx.xowa.xtns.pfuncs.times; import gplx.*; import gplx.xowa.*; import gplx.xowa.xtns.*; import gplx.xowa.xtns.pfuncs.*; +import gplx.core.brys.*; +class Pxd_itm_unit_relative extends Pxd_itm_base implements Pxd_itm_prototype { // handle "next", "prev", "this"; EX: "next year" + private final int adj; + public Pxd_itm_unit_relative(int adj, int ary_idx) { + this.adj = adj; + Ctor(ary_idx); + } + @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 boolean Eval(Pxd_parser state) { + // find next token: EX: year, month, Sunday, Monday, etc. + Pxd_itm itm = Pxd_itm_.Find_fwd__non_ws(state.Tkns(), this.Ary_idx() + 1); + if (itm == null) { + state.Err_set(Pft_func_time_log.Invalid_date, Bfr_arg_.New_int(adj)); + return false; + } + + switch (itm.Tkn_tid()) { + // EX: "next year", "next month", etc. + case Pxd_itm_.Tid_unit: + Pxd_itm_unit unit_tkn = (Pxd_itm_unit)itm; + unit_tkn.Unit_seg_val_(adj); + break; + // EX: "next Monday", "next Tuesday", etc. + case Pxd_itm_.Tid_dow_name: + Pxd_itm_dow_name day_tkn = (Pxd_itm_dow_name)itm; + day_tkn.Relative_adj_(adj); + break; + default: + state.Err_set(Pft_func_time_log.Invalid_date, Bfr_arg_.New_int(adj)); + return false; + } + return true; + } + + @Override public boolean Time_ini(Pxd_date_bldr bldr) { + // noop; date-logic handled by respective unit, month, dow classes; EX: "next month" -> "next" does no date logic; "month" does; + return true; + } + public static final Pxd_itm_unit_relative + Next = new Pxd_itm_unit_relative( 1, 0) + , Prev = new Pxd_itm_unit_relative(-1, 0) + , This = new Pxd_itm_unit_relative( 0, 0) + ; +} diff --git a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_parser.java b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_parser.java index 9f5082422..b0cc9745d 100644 --- a/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_parser.java +++ b/400_xowa/src/gplx/xowa/xtns/pfuncs/times/Pxd_parser.java @@ -143,8 +143,10 @@ class Pxd_parser { return DateAdp_.MinValue; } } + + // build date DateAdp now = Datetime_now.Get(); - DateAdpBldr bldr = new DateAdpBldr(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0); + Pxd_date_bldr bldr = new Pxd_date_bldr(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0); for (int i = 0; i < tkns_len; i++) { Pxd_itm itm = (Pxd_itm)tkns[i]; if (!itm.Time_ini(bldr)) { @@ -152,7 +154,7 @@ class Pxd_parser { return null; } } - return bldr.Bld(); + return bldr.To_date(); } private void MakeDataAry() { data_ary = new Pxd_itm[tkns_len]; data_ary_len = 0;