Opdrts is short for "Opinion Poll Date Range Table Sorting", following the naming style of {{Date table sorting}}, to show DMY format date ranges in opinion poll article tables. I wanted to use a somewhat obscure name so better names are left available for any future more general purpose template, and a compact name as it would be heavily used in table rows.

A big advantage of using this template compared to the hand-written expansion, besides ease-of-use and compactness, is that ndash and hyphen are used correctly, so the sort order works correctly. In converting old hand-written versions to use the template many such errors (copy-and-pasted forward) were discovered, plus simple errors like the wrong year in data-sort-value, which were hard to identify in the visual form.

Usage edit

All parameters are positional, and date elements are a single numeric, or for the month optionally in 3-letter text form eg "Jan" (i.e. not full textual month) as an alternative to "01":

{{opdrts |Start Day (optional)|End Day|End Month|End Year|"year" (optional formatting instruction)}}

The template displays the range using the recommended style for Opinion polling for the next United Kingdom general election (see examples below), and generates a data-sort-value from the end date for correct table sorting. The default format is suitable to single year tables, with the "year" format suitable for multi-year tables.

If Start Day is greater than End Day it is taken to be in the previous month; if End Month is January, Dec is used for the displayed start month, but for compactness without its year (one less than End Year) being shown.

Examples edit

{{opdrts|14|15|Oct|2020}} → data-sort-value="2020-10-15"|14–15 Oct
{{opdrts|30|2|10|2020}} → data-sort-value="2020-10-02"|30 Sep2 Oct
{{opdrts||24|Aug|2020}} → data-sort-value="2020-08-24"|24 Aug
{{opdrts||12|12|2019|year}} → data-sort-value="2019-12-12"|12 Dec 2019
{{opdrts|27|2|Jan|2020|year}} → data-sort-value="2020-01-02"|27 Dec2 Jan 2020

Pseudo-code edit

'data-sort-value="$4-numeric($3)-pad2digit($2)"|'

if $1
then
        if $1 > $2
        then '$1 month($3 - 1) – '
        else '$1–'
        fi
fi

'$2 month($3)'

if $5 = "year"
then ' $4'
fi

Implementation notes edit

Makes use of the zero month feature of #time (derived from PHP strtotime) so January-1 goes to December previous year.

Note 5th format param could be extended eg with "ddM" (default), "ddm" (full month name), "ddMy" (equiv to "year") and with different output orders. If this is done, should probably re-implement in Lua.

Limit: A poll can take no longer than one month, because of the simplified usage syntax. If this should ever happen, you'll need to produce the text manually. (We could extend the 1st param to optionally be a full date if removing the limit became important.)

Bug workaround: The seemingly unnecessary use of {{padleft:}} is to work around a seeming bug in #time for dates like "2020-Oct-5" which generate as if it was "2020-Oct-1 5am", taking the 5 as if 5am:

#time: Y-m-d & r of "2020-Oct-5" generates: 2020-10-01 & Thu, 01 Oct 2020 05:00:00 +0000

whereas slight variations work correctly:

#time: Y-m-d & r of "2020-Oct-05" generates: 2020-10-05 & Mon, 05 Oct 2020 00:00:00 +0000
#time: Y-m-d & r of "2020-10-5" generates: 2020-10-05 & Mon, 05 Oct 2020 00:00:00 +0000

Bug workaround (added 11 August 2023‎): It appears there is a limit to the number of parser-function #time expansions that work in article, that first appeared in August 2023 as Opinion polling for the next United Kingdom general election grew larger, at about 2500 uses of #time. It manifests itself inconsistently (sometimes opdrts works fine, sometimes not) with red "Error: Total length of format strings for #time exceeds 6000 bytes" and "Error: Invalid time" messages appearing in the article. This limit is not given in the #time documentation, but is alluded to in MediaWiki talk:Pfunc time too long. To workaround I added code for the common case to use one fewer #time for the pseudo-code '$2 month($3)' expansion, which nearly halves the number of times #time is used, so allowing nearly double the Opdrts uses in an article - which means we are very unlikely to hit this limit again. The workaround is that for 3-character month params, it is expanded directly rather than via #time, though this has the effect of eg "oct" goes into the output rather than converted to "Oct" ("010" still creates an error earlier at data-sort-value generation) - but that's immediately visible so the user can easily fix.

Note: There is some discussion on using this template at Talk:Opinion polling for the next United Kingdom general election/Archive_4#New template for easier/reliable date ranges.

Converting existing text to use opdrts edit

I have developed a rather horrid GNU sed script to convert prior WP articles to use opdrts. You will need a Unix/Linux/clone system to do this, and if the wiki source has non-ASCII in it you must run sed in the "C" locale for correct operation. Copy and paste the text to a file on the system, run the GNU sed script below on the file, then carefully check the output to make sure the conversion is correct; if there are mistakes or oddities, eg the data-sort-value year not matching the date year, the script will generate some incorrect output:

/data-sort-value="/{
# note debug tags like "2: " are inserted then removed at end
# convert unusual dashes to -
s/\(\x96\|\d196\|\d150\|\d151\|\o226\)/-/g
# eg data-sort-value="2021-03-01"|28 Feb - 1 Mar
s/data-sort-value="\(20[0-9][0-9]\)[-–][0-1][0-9][-–][0-3][0-9]" *;* *| *\([0-9]\+\)  *[JFMAMJJASOND][a-z][a-z] *\(-\|–\|–\) *\([0-9]\+\)  *\([JFMAMJJASOND][a-z][a-z]\) *\(\1\?\)/1: {{opdrts|\2|\4|\5|\1|MAYBE\6}}/
# eg data-sort-value="2021-03-05"|2-5 Mar
s/data-sort-value="\(20[0-9][0-9]\)[-–][0-1][0-9][-–][0-3][0-9]" *;* *| *\([0-9]\+\) *\(-\|–\|–\) *\([0-9]\+\)  *\([JFMAMJJASOND][a-z][a-z]\) *\(\1\?\)/2: {{opdrts|\2|\4|\5|\1|MAYBE\6}}/
# eg data-sort-value="2021-03-15"|15 Mar
s/data-sort-value="\(20[0-9][0-9]\)[-–][0-1][0-9][-–][0-3][0-9]" *;* *| *\([0-9]\+\)  *\([JFMAMJJASOND][a-z][a-z]\) *\(\1\?\)/3: {{opdrts||\2|\3|\1|MAYBE\4}}/
s/|MAYBE}}/}}/
s/|MAYBE20..}}/|year}}/
}

# # if your dates have no data-sort-value, you can try this little tested code, but check output very carefully:
# 
# /| *\([0-9]\+\).* \([JFMAMJJASOND][a-z][a-z]\)  *\(20[0-9][0-9]\)/{
# s/\(\x96\|\d196\|\d150\|\d151\|\o226\)/-/g
# # eg 28 Feb - 1 Mar 2021
# s/| *\([0-9]\+\)  *[JFMAMJJASOND][a-z][a-z] *\(-\|–\|–\) *\([0-9]\+\)  *\([JFMAMJJASOND][a-z][a-z]\) *\(20[0-9][0-9]\)/|4: {{opdrts|\1|\3|\4|\5|year}}/
# # eg 2-5 Mar 2021
# s/| *\([0-9]\+\) *\(-\|–\|–\) *\([0-9]\+\) *\([JFMAMJJASOND][a-z][a-z]\) *\(20[0-9][0-9]\)/|5: {{opdrts|\1|\3|\4|\5|year}}/
# # eg 5 Mar 2021
# s/| *\([0-9]\+\) *\([JFMAMJJASOND][a-z][a-z]\) *\(20[0-9][0-9]\)/|6: {{opdrts||\1|\2|\3|year}}/
# # fixup style
# s/^\(| *style=.*\)|.: {{opdrts|/\1{{opdrts|/
# }
#
# /^| *[0-9]\+.*[JFMAMJJASOND][a-z][a-z] *$/{
# s/\(\x96\|\d196\|\d150\|\d151\|\o226\)/-/g
# # eg 28 Feb - 1 Mar
# s/^| *\([0-9]\+\)  *[JFMAMJJASOND][a-z][a-z] *\(-\|–\|–\) *\([0-9]\+\)  *\([JFMAMJJASOND][a-z][a-z]\) *\(\1\?\)/|4: {{opdrts|\1|\3|\4|2021}}/
# # eg 2-5 Mar
# s/^| *\([0-9]\+\) *\(-\|–\|–\) *\([0-9]\+\) *\([JFMAMJJASOND][a-z][a-z]\)/|5: {{opdrts|\1|\3|\4|2021}}/
# # eg 5 Mar
# s/^| *\([0-9]\+\) *\([JFMAMJJASOND][a-z][a-z]\)/|6: {{opdrts||\1|\2|2021}}/
# }

# remove debugging tags:
s/[123456]: {{opdrts/{{opdrts/
# cleanup leading/trailing space
s/^|  *{{opdrts/|{{opdrts/
/^|{opdrts/s/ *$//

It uses the GNU extension \? so pre-GNU versions of sed won't work. Here are example commands to do the job assuming opdrts.sed is the script above and article.old is the wikipedia article text:

LC_ALL=C sed -f opdrts.sed article.old > article.new
# visual checks:
grep data-sort-value article.new
egrep "opdrts| [JFMAMJJASOND][a-z][a-z] *$" article.new
diff article.old article.new
# see if you have dates with year in original without a data-sort-value:
grep -v data-sort-value article.old | grep --color "[0-9] [JFMAMJJASOND][a-z][a-z] 20[12][0-9]"

See also edit

  • {{daterangedash}}: simple date range with full month names and no data-sort-value
  • {{Date table sorting}}: more general but for a single date not a range
  • {{Opmdrts}}: a variant generating North American style dates