Markus, Fabian, and all:

Lots of code in this patch. Now that the Gregorian and Julian conversions and back-conversions have been proved, this patch will create a version that computes and outputs both. Specifically, it:

1.   Adds another set of day, month, and year parts.

2.   Creates separate caches for a Gregorian and a Julian printout value.

3. Loads each set of year-month-day properties according to a calendar model that is either specified or worked out from the input. By default, the model to be used to create the Julian Day is the Gregorian, if the date is October 15, 1582 or later, and otherwise the Julian. But the user may override this rule by specifying "Gr" or "Jl" in his input. (If he uses "OS" in English, that means "increment the year if the date falls between 1 January and 24 March inclusive, and treat the resulting date as Julian."

4.   Performs /both/ back-conversions and stores each result separately.

5. Preserves the imprecision of the input, i.e. a month and a year as input produces only a month and a year as output in each model.

6. Selects the printout value for the browser as follows: any date having a JD less than the date of the Gregorian calendar proclamation will be Julian; otherwise it will be Gregorian.

7. Creates "tooltip captions" that show the Gregorian value, then the Julian.

At this point I'm open to suggestions as to which outputs would be preferable. I can now produce whatever output is desired.

Now that I have shown this, I will proceed to implement the two other calendar models that I mentioned.

The next step after that will probably be the transfer of these improvements to the current version. Only then will I be in a position to add the calendar model as another DBkeys element, probably $args[1]. (How many elements is $args permitted to have in the functions getDBKeys() and parseDBkeys($args)? I had the distinct impression that in SMW 1.4.2, the answer was two, corresponding to the old arguments $value and $unit.)

Temlakos
--- ../SemanticMediaWiki-lng/SMW_DV_Time.php    2009-08-11 17:05:23.000000000 
-0400
+++ ./SMW_DV_Time.php   2009-08-11 21:09:18.000000000 -0400
@@ -20,12 +20,16 @@
  * All dates are supposed to refer either to the Gregorian calendar (October 
15, 1582
  * or later), or to the Julian calendar (earlier than October 15, 1582 
Gregorian). Any
  * date specified between October 5 and October 14, 1582 inclusive, will be 
recalculated
- * according to the Julian calendar. The "OS" (Old Style) symbol is supported 
in English,
- * and dates annotated with this symbol are processed accordingly: the year is 
incremented
- * by one if the date falls between 1 January and 24 March inclusive, and the 
resultant
- * day is converted according to Julian rules, but the printout is either 
Gregorian or
- * Julian according to the epoch. Other calendar-model support is planned.
- * Historical dates are, however, still experimental.
+ * according to the Julian calendar. But users may override the default 
calculation by
+ * specifying "Gr" for Gregorian or "Jl" for Julian, as desired.
+ * The "OS" (Old Style) symbol is supported in English, and dates annotated 
with this
+ * symbol are processed accordingly: the year is incremented by one if the 
date falls
+ * between 1 January and 24 March inclusive, and the resultant day is converted
+ * according to Julian rules, but the printout is either Gregorian or
+ * Julian according to the epoch.
+ *
+ * Other calendar-model support is planned. Historical dates are, however,
+ * still experimental.
  *
  * This type can handle dates across history with full precision for storing, 
and
  * substantial precision for sorting and querying. The range of supported past 
dates
@@ -77,7 +81,8 @@
 
        protected $m_wikivalue; // a suitable wiki input value
        protected $m_xsdvalue = false; // cache for XSD value
-       protected $m_printvalue = false; // cache for printout value
+       protected $m_gregvalue = false; // cache for (proleptic) Gregorian value
+       protected $m_julvalue = false; // cache for (proleptic) Julian value
        protected $m_pref = false; // holds a symbol for the calendar model
        protected $m_day = false; //Gregorian day, remains false if unspecified
        protected $m_month = false; //Gregorian month, remains false if 
unspecified
@@ -87,6 +92,9 @@
        protected $m_format = false; // number of parts of the date that were 
specified
        protected $m_timeoffset; //contains offset (e.g. timezone) 
        protected $m_timeannotation; //contains am or pm
+       protected $m_dayj = false; // Julian day, remains false if unspecified
+       protected $m_monthj = false; // Julian month, remains false if 
unspecified
+       protected $m_yearj = false; // Julian year, remains false if unspecified
        // The following are constant (array-valued constants are not 
supported, hence the decalration as variable):
        protected $m_months = array("January", "February", "March", "April" , 
"May" , "June" , "July" , "August" , "September" , "October" , "November" , 
"December");
        protected $m_monthsshort = array("Jan", "Feb", "Mar", "Apr", "May", 
"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
@@ -124,6 +132,9 @@
                $this->m_timeoffset = 0;
                $this->m_timeannotation = false;
                $this->m_format = false;
+               $this->m_dayj = false;
+               $this->m_monthj = false;
+               $this->m_yearj = false;
 
                $value = trim($value); // ignore whitespace
                $this->m_wikivalue = $value;
@@ -232,11 +243,15 @@
 
                $digitcount = count($array)-1; //number of digits - 1 is used 
as an array index for $dateformats
                $found = false;
+               $prelimModel = $this->findPrelimModel();
                foreach ($dateformats[$digitcount] as $format) { //check 
whether created band matches dateformats
                        if (!(~$band & $format)) { //check if $format => $band 
("the detected band supports the current format")
                                $i = 0;
                                foreach ($this->m_formats[$format] as 
$globalvar) { // map format digits to internal variables
                                        $globalvar = 'm_'.$globalvar; // (for 
searching this file) this is one of: m_year, m_month, m_day
+                                       if($prelimModel == 'Jl') {
+                                               $globalvar = $globalvar . 'j';
+                                       }
                                        if (!$this->$globalvar) 
$this->$globalvar = intval($array[$i]);
                                        $i++;
                                }
@@ -254,7 +269,11 @@
                        wfLoadExtensionMessages('SemanticMediaWiki');
                        
$this->addError(wfMsgForContent('smw_nodatetime',$value));
                        return true;
-               } elseif ( ($this->m_year < -4713) && ($this->m_timeoffset != 
0) ) { //no support for time offsets if year < -4713
+               } elseif ( ($this->m_dayj > 0) && ($this->m_dayj > 
$this->m_daysofmonths[$this->m_monthj]) ) { //date does not exist in Julian 
calendar
+                       wfLoadExtensionMessages('SemanticMediaWiki');
+                       
$this->addError(wfMsgForContent('smw_nodatetime',$value));
+                       return true;
+               } elseif ( ($this->m_year == false) && ($this->m_yearj < -4713) 
&& ($this->m_timeoffset != 0) ) { //no support for time offsets if year < -4713
                        wfLoadExtensionMessages('SemanticMediaWiki');
                        
$this->addError(wfMsgForContent('smw_nodatetime',$value));
                        return true;
@@ -262,15 +281,15 @@
 
                // Handle OS: Increment the year if earlier than March 25.
                if ($this->m_pref == 'OS') {
-                       if(($this->m_month < 3) || (($this->m_month == 3) && 
($this->m_day < 25))) {
-                               $this->m_year++;
+                       if(($this->m_monthj < 3) || (($this->m_monthj == 3) && 
($this->m_dayj < 25))) {
+                               $this->m_yearj++;
                        } 
                }
 
                // Handle BC: the year is negative.
                if ($is_yearbc) {
-                       if ($this->m_year > 0) { // see class documentation on 
BC, "year 0", and ISO conformance ...
-                               $this->m_year = -($this->m_year);
+                       if ($this->m_yearj > 0) { // see class documentation on 
BC, "year 0", and ISO conformance ...
+                               $this->m_yearj = -($this->m_yearj);
                        }
                }
 
@@ -279,7 +298,11 @@
                if ($this->m_jd > -0.5) {
                        $this->m_jd = $this->m_jd - $this->m_timeoffset;
                        $this->JD2Date();
-               }
+               } else {
+                       $this->m_day = $this->m_dayj;
+                       $this->m_month = $this->m_monthj;
+                       $this->m_year = $this->m_yearj;
+               } // Copy Julian registers into Gregorian registers; needed for 
the XSD value
 
                if ($this->m_caption === false) {
                        $this->m_caption = $value;
@@ -287,26 +310,49 @@
                return true;
        }
 
-       protected function checkDigit($digit){
+       protected function findMonth($label) {
                global $smwgContLang;
+               $retVal = $smwgContLang->findMonth($label);
+               if ( $retVal !== false ) {
+                       return $retVal;
+               }
+               $retVal = array_search($label, $this->m_months);
+               if ( $retVal !== false ) {
+                       return $retVal + 1;
+               }
+               $retVal = array_search($label, $this->m_monthsshort);
+               if ( $retVal !== false ) {
+                       return $retVal + 1;
+               }
+               return false;
+       }
+
+       protected function findPrelimModel() {
+               if(($this->m_pref == 'BC') || ($this->m_pref == 'Jl') || 
($this->m_pref == 'OS')) {
+                       return 'Jl'; // Assume Julian model if specified in any 
way, shape or form.
+               }
+               return 'Gr';
+       }
+
+       protected function checkDigit($digit){
                if(!is_numeric($digit)){ //check for alphanumeric day or month 
value
+                       $prelimModel = $this->findPrelimModel();
                        if(preg_match("/[0-3]?[0-9](st|nd|rd|th)/u", $digit)) { 
//look for day value terminated by st/nd/th
-                               $this->m_day = 
intval(substr($digit,0,strlen($digit)-2)); //remove st/nd/th
+                               $dayVal = 
intval(substr($digit,0,strlen($digit)-2)); //remove st/nd/th
+                               if($prelimModel == 'Jl') {
+                                       $this->m_dayj = $dayVal;
+                               } else {
+                                       $this->m_day = $dayVal;
+                               }
                                return SMW_DAY;
                        }
-                       $monthnumber = $smwgContLang->findMonth($digit);
-                       if ( $monthnumber !== false ) {
-                               $this->m_month = $monthnumber;
-                               return SMW_MONTH;
-                       }
-                       $monthnumber = array_search($digit, $this->m_months);
-                       if ( $monthnumber !== false ) {
-                               $this->m_month = $monthnumber + 1;
-                               return SMW_MONTH;
-                       }
-                       $monthnumber = array_search($digit, 
$this->m_monthsshort);
+                       $monthnumber = $this->findMonth($digit);
                        if ( $monthnumber !== false ) {
-                               $this->m_month = $monthnumber + 1;
+                               if($prelimModel == 'Jl') {
+                                       $this->m_monthj = $monthnumber;
+                               } else {
+                                       $this->m_month = $monthnumber;
+                               }
                                return SMW_MONTH;
                        }
                        return 0;
@@ -323,6 +369,9 @@
 
        // finds the appropriate model to use.
        protected function findModel() {
+               if ($this->m_pref == 'BC') {
+                       return 'Jl'; // BC dates are automatically Julian.
+               }
                if ($this->m_pref == 'OS') {
                        $this->m_pref = ''; // Erase the OS marker; it will not 
be needed after this.
                        return 'Jl'; // Old Style dates are converted per 
Julian rules.
@@ -339,7 +388,10 @@
                }
                if (($this->m_year == 1582) && ($this->m_month == 10) && 
($this->m_day > 4)) {
                        return 'Gr';
-               } // Set $model to 'Jl'
+               } // Set $model to 'Jl' and move all specified date parts to 
the Julian set.
+               $this->m_dayj = $this->m_day;
+               $this->m_monthj = $this->m_month;
+               $this->m_yearj = $this->m_year;
                return 'Jl';
        }
 
@@ -349,17 +401,33 @@
                if (count($d)==3) 
list($this->m_year,$this->m_month,$this->m_day) = $d;
                elseif (count($d)==2) list($this->m_year,$this->m_month) = $d;
                elseif (count($d)==1) list($this->m_year) = $d;
-               $this->createJD($this->findModel());
+               if($this->m_year < -4713) {
+                       $this->m_yearj = $this->m_year;
+                       $this->m_monthj = $this->m_month;
+                       $this->m_dayj = $this->m_day;
+                       $this->createJD('Jl'); // This date falls earlier than 
the Julian Era.
+               } else {
+                       $this->createJD('Gr'); // This is a Gregorian or 
proleptic Gregorian date
+               }
                if($this->m_jd > -0.5) {//Back-convert only if the JD is 
suitable for that
                        $this->JD2Date();
                }
                $this->makePrintoutValue();
-               $this->m_caption = $this->m_printvalue;
-               $this->m_wikivalue = $this->m_printvalue;
+               $this->m_caption = ($this->m_jd < self::J1582) ? 
$this->m_julvalue : $this->gregvalue;
+               $this->m_wikivalue = ($this->m_jd < self::J1582) ? 
$this->m_julvalue : $this->gregvalue;
        }
 
        public function getShortWikiText($linked = NULL) {
-               return $this->m_caption;
+               if ($this->isValid() && ($linked !== NULL) && ($linked !== 
false)) {
+                       $this->makeGregorianValue();
+                       $this->makeJulianValue();
+                       SMWOutputs::requireHeadItem(SMW_HEADER_TOOLTIP);
+                       return '<span class="smwttinline">' . $this->m_caption 
. '<span class="smwttcontent">' .
+                               $this->m_gregvalue . ' <br />' .
+                               $this->m_julvalue . '</span></span>';
+               } else {
+                       return $this->m_caption;
+               }
        }
 
        public function getShortHTMLText($linker = NULL) {
@@ -371,7 +439,7 @@
                        return $this->getErrorText();
                } else {
                        $this->makePrintoutValue();
-                       return $this->m_printvalue;
+                       return ($this->m_jd < self::J1582) ? $this->m_julvalue 
: $this->m_gregvalue;
                }
        }
 
@@ -419,8 +487,13 @@
         * Return the year as a number corresponding to the year in the Julian 
or
         * Gregorian calendar and using the astronomical year numbering (0 
means 1 BC).
         */
-       public function getYear() {
-               return $this->m_year;
+       public function getYear($model = 'Gr') {
+               switch ($model) {
+                       case 'Jl':
+                               return $this->m_yearj;
+                       default:
+                               return $this->m_year;
+               }
        }
 
        /**
@@ -430,8 +503,13 @@
         * if the date is valid but has no explicitly specified month. It can
         * also be set to FALSE to detect this situation.
         */
-       public function getMonth($default = 1) {
-               return ($this->m_month != false)?$this->m_month:$default;
+       public function getMonth($model = 'Gr', $default = 1) {
+               switch ($model) {
+                       case 'Jl':
+                               return ($this->m_monthj != 
false)?$this->m_monthj:$default;
+                       default:
+                               return ($this->m_month != 
false)?$this->m_month:$default;
+               }
        }
 
        /**
@@ -440,8 +518,13 @@
         * if the date is valid but has no explicitly specified date. It can
         * also be set to FALSE to detect this situation.
         */
-       public function getDay($default = 1) {
-               return ($this->m_day != false)?$this->m_day:$default;
+       public function getDay($model = 'Gr', $default = 1) {
+               switch ($model) {
+                       case 'Jl':
+                               return ($this->m_dayj != 
false)?$this->m_dayj:$default;
+                       default:
+                               return ($this->m_day != 
false)?$this->m_day:$default;
+               }
        }
 
        /**
@@ -482,26 +565,52 @@
        }
 
        /**
-        * Build a preferred value for printout, also used as a caption when 
setting up values
+        * Build preferred values for printout, to be used as captions when 
setting up values
         * from the store.
         */
        protected function makePrintoutValue() {
+               $this->makeGregorianValue();
+               $this->makeJulianValue();
+       }
+
+       protected function makeGregorianValue() {
                global $smwgContLang;
-               if ($this->m_printvalue === false) {
+               if ($this->m_gregvalue === false) {
                        //MediaWiki date function is not applicable any more 
(no support for BC Dates)
                        if ($this->m_year > 0) {
-                               $this->m_printvalue = 
number_format($this->m_year, 0, '.', ''); // note: there should be no digits 
after the comma anyway
+                               $this->m_gregvalue = 
number_format($this->m_year, 0, '.', ''); // note: there should be no digits 
after the comma anyway
                        } else {
-                               $this->m_printvalue = 
number_format(-($this->m_year), 0, '.', '') . ' BC'; // note: there should be 
no digits after the comma anyway
+                               $this->m_gregvalue = 
number_format(-($this->m_year), 0, '.', '') . ' BC'; // note: there should be 
no digits after the comma anyway
                        }
                        if ($this->m_month) {
-                               $this->m_printvalue =  
$smwgContLang->getMonthLabel($this->m_month) . " " . $this->m_printvalue;
+                               $this->m_gregvalue =  
$smwgContLang->getMonthLabel($this->m_month) . " " . $this->m_gregvalue;
                        }
                        if ($this->m_day) {
-                               $this->m_printvalue =  $this->m_day . " " . 
$this->m_printvalue;
+                               $this->m_gregvalue =  $this->m_day . " " . 
$this->m_gregvalue;
+                       }
+                       if ($this->m_time) {
+                               $this->m_gregvalue .= " " . $this->m_time;
+                       }
+               }
+       }
+
+       protected function makeJulianValue() {
+               global $smwgContLang;
+               if ($this->m_julvalue === false) {
+                       //MediaWiki date function is not applicable any more 
(no support for BC Dates)
+                       if ($this->m_yearj > 0) {
+                               $this->m_julvalue = 
number_format($this->m_yearj, 0, '.', ''); // note: there should be no digits 
after the comma anyway
+                       } else {
+                               $this->m_julvalue = 
number_format(-($this->m_yearj), 0, '.', '') . ' BC'; // note: there should be 
no digits after the comma anyway
+                       }
+                       if ($this->m_monthj) {
+                               $this->m_julvalue =  
$smwgContLang->getMonthLabel($this->m_monthj) . " " . $this->m_julvalue;
+                       }
+                       if ($this->m_dayj) {
+                               $this->m_julvalue =  $this->m_dayj . " " . 
$this->m_julvalue;
                        }
                        if ($this->m_time) {
-                               $this->m_printvalue .= " " . $this->m_time;
+                               $this->m_julvalue .= " " . $this->m_time;
                        }
                }
        }
@@ -562,27 +671,27 @@
        /// Calculate a Julian day according to Gregorian calendar rules
        protected function gregorian2JD(){
                $this->m_jd = 0;
-               $a = intval((14-$this->getMonth())/12);
+               $a = intval((14-$this->getMonth('Gr'))/12);
                $y = $this->m_year + 4800 - $a;
-               $m = $this->getMonth() + 12 * $a - 3;
-               $this->m_jd += $this->getDay() + intval((153*$m+2)/5) + 365*$y 
+ intval($y/4) - intval($y/100) + intval($y/400) - 32045.5;
+               $m = $this->getMonth('Gr') + 12 * $a - 3;
+               $this->m_jd += $this->getDay('Gr') + intval((153*$m+2)/5) + 
365*$y + intval($y/4) - intval($y/100) + intval($y/400) - 32045.5;
                $this->m_format = ($this->m_day != false) ? 3 : 
(($this->m_month != false) ? 2 : 1);
        }
 
        /// Calculate a Julian day according to Julian calendar rules
        protected function julian2JD(){
-               if ($this->m_year >= -4713) {
+               if ($this->m_yearj >= -4713) {
                        $this->m_jd = 0;
-                       $y1 = ($this->m_year < 1) ? ($this->m_year + 1) : 
$this->m_year;
-                       $m1 = $this->getMonth();
+                       $y1 = ($this->m_yearj < 1) ? ($this->m_yearj + 1) : 
$this->m_yearj;
+                       $m1 = $this->getMonth('Jl');
                        $y2 = ($m1 <= 2) ? ($y1 - 1) : $y1;
                        $m2 = ($m1 <= 2) ? ($m1 + 12) : $m1;
-                       $this->m_jd += intval((365.25 * ($y2 + 4716))) + 
intval((30.6001 * ($m2+1))) + $this->getDay() - 1524.5;
+                       $this->m_jd += intval((365.25 * ($y2 + 4716))) + 
intval((30.6001 * ($m2+1))) + $this->getDay('Jl') - 1524.5;
                } else { // starting from the time when JD would be negative, 
use our own "stretched" representation, currently this just ignores local time
-                       $time = 1 - (($this->getMonth() / 12) + 
($this->getDay() / 365));
-                       $this->m_jd = $this->m_year - $time;
+                       $time = 1 - (($this->getMonth('Jl') / 12) + 
($this->getDay('Jl') / 365));
+                       $this->m_jd = $this->m_yearj - $time;
                }
-               $this->m_format = ($this->m_day != false) ? 3 : 
(($this->m_month != false) ? 2 : 1);
+               $this->m_format = ($this->m_dayj != false) ? 3 : 
(($this->m_monthj != false) ? 2 : 1);
        }
 
        /// Convert the Julian Day fraction to the time string.
@@ -599,11 +708,8 @@
 
        /// Convert Julian Day to m_year, m_month, and m_day according to the 
proper model.
        protected function JD2Date() {
-               if($this->m_jd < self::J1582) {
-                       $this->JD2Julian();
-               } else {
-                       $this->JD2Gregorian();
-               }
+               $this->JD2Julian();
+               $this->JD2Gregorian();
                if($this->m_time != false) { // Do not fill this in if it was 
not filled in to begin with
                        $this->fracToTime();
                }
@@ -636,9 +742,9 @@
                $e = intval(($b - $d)/30.6001);
                $m = intval(($e < 14) ? ($e - 1) : ($e - 13));
                $y = intval(($m > 2) ? ($c - 4716) : ($c - 4715));
-               $this->m_year = ($y < 1) ? ($y - 1) : $y;
-               $this->m_month = ($this->m_format >= 2) ? $m : false;
-               $this->m_day = ($this->m_format == 3) ? ($b - $d - 
intval(30.6001 * $e)) : false;
+               $this->m_yearj = ($y < 1) ? ($y - 1) : $y;
+               $this->m_monthj = ($this->m_format >= 2) ? $m : false;
+               $this->m_dayj = ($this->m_format == 3) ? ($b - $d - 
intval(30.6001 * $e)) : false;
        }
 
 }
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Semediawiki-devel mailing list
Semediawiki-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/semediawiki-devel

Reply via email to