Adding superscripts to ordinal publishing dates for entries in Hugo and WordPress
5th January 2025These web publishing tools differ and so the solutions, yet the use case is the same: displaying ordinal dates for entries in a blog or website. Also, the wish is to have the ordinal suffix superscripted as in normal English usage. Let us take each platform in turn.
Hugo
Given that is programming in Go, it is little surprise that Hugo uses Go’s time formatting syntax. Thus, my starting point was as follows:
{{ .Date.Format "15:04, January 2, 2006" }}
The result from the above looks like this: 20:56, January 2, 2025. Unfortunately, Go does not support ordinal dates in its time formatting, so adding them needs more extensive conditional logic like what you see below. The default suffix is th
, while nd
is added for the second and twenty-second days of the month and rd
is added for the third and twenty-third days. This how things now look:
{{ .Date.Format "15:04, January 2" }}{{ if eq (.Date.Format "2") "2" }}nd{{ else if eq (.Date.Format "2") "22" }}nd{{ else if eq (.Date.Format "2") "1" }}st{{ else if eq (.Date.Format "2") "21" }}st{{ else if eq (.Date.Format "2") "3" }}rd{{ else if eq (.Date.Format "2") "23" }}rd{{ else }}th{{ end }}, {{ .Date.Format "2006" }}
That gives you something like 20:56, January 2nd, 2025. The handy thing about Hugo is that it primarily is an HTML output engine, so adding superscripting tags in the right places, like below, superscripts the ordinal suffixes as needed. Here, the tags are shown in bold for emphasis.
{{ .Date.Format "15:04, January 2" }}<sup>{{ if eq (.Date.Format "2") "2" }}nd{{ else if eq (.Date.Format "2") "22" }}nd{{ else if eq (.Date.Format "2") "1" }}st{{ else if eq (.Date.Format "2") "21" }}st{{ else if eq (.Date.Format "2") "3" }}rd{{ else if eq (.Date.Format "2") "23" }}rd{{ else }}th{{ end }}</sup>, {{ .Date.Format "2006" }}
Once you have that: this is how things appear: 20:56, January 2nd, 2025, which gets the job done.
WordPress
Hugo produces the website for you to upload it to the web server; it is static after that. In contrast, WordPress is based on PHP and dynamically renders a web page when it is requested. That means that components are generated at that time. Thus, the following code snippet outputs a date when a website post or page has been published:
<?php the_time('jS F Y') ?>
PHP time and date formatting does account for ordinal dates, unlike what you get in Go. Here, the jS F Y
forma controls how the date gets displayed. The codes do the following: j outputs the day in the month without a leading zero, S adds the ordinal suffix, F adds the full month name and Y adds the four digit year. The result then is something like this: 1st January 2025. To superscript the ordinal suffix, the following change is needed (the addition is emboldened for emphasis):
<?php the_time('j\<\s\u\p\>S\<\/\s\u\p\> F Y') ?>
Here, the HTML superscript tags are inserted into the format with every character escaped by a leading backslash (\). While PHP does generate HTML, it needs the escaping to preserve the intended input here. Security considerations like preventing cross-site scripting also matter, though maybe not so much in this context. Regardless of the technicality, the result becomes 1st January 2025, which is what was sought.
Pandemic camera
8th September 2024Back at the end of 2019, I acquired a Canon EOS 90D, possibly the swansong for mid-range Canon SLR cameras. Much effort is going into mirrorless cameras, yet I retain affection for SLR cameras because of their optical viewfinders. That may have been part of the reason for the acquisition, when I already had an ageing Pentax K5 Mark II. Buying SLR cameras is one way to keep them in production.
Little did I know what lay ahead in 2020 at that stage. Until recently, this was not to be a camera that travelled widely, such were the restrictions. Nevertheless, battery life is superb and handling is good too. The only absence is not having a level in the viewfinder like the Pentax K3 Mark III or maybe any mirrorless camera.
The newer file type of CR3 caught me out at first until I adjusted my command line tooling to deal with that. File sizes were larger as well, which has an impact on storage. Otherwise, there was little to change in my workflow. That would take other technological changes, like the increasing amount of AI being built into Adobe software.
Outdoor photography is my mainstay, and it excelled at that. The autofocus works well on its 24 to 135 mm zoom lens, except perhaps from focussing on skyscapes at times. Metering produced acceptable results, though it differed from the Pentax output to which I had become accustomed. All in all, it slipped into a role like other cameras that I had.
Throughout 2020 and 2021, it provided the required service alongside other cameras that I had. The aforementioned Pentax remained in use, like an Olympus and another Canon. Overseas travel curtailed horizons, so it was around local counties like Cheshire, Derbyshire, Staffordshire and Shropshire. In September 2020, it travelled to Llandudno in North Wales, an exception to the general trend of English hikes and cycles.
Since then, it has been superseded, though. A Pentax K3 Mark III made it into my possession to become my main camera, returning me near enough to my pre-2020 practice. Curiosity about Canon mirrorless options added a Canon EOS RP and a 24 to 240 mm zoom lens. That has shorter battery life than is ideal, and its level is not as helpful as that on the Pentax K3 Mark III or the aforementioned Olympus. If anything, it may get replaced while the EOS 90D remains. My getting a new base in Ireland means that it has gone there to save me carrying a camera there from England. That should give it a new lease of life.
Using a BASH command to count the files in a directory
12th March 2024As part of my backup workflow, I maintain a machine running OpenMediaVault that I only power up when backups are to be performed. Typically, this often happens when I have new photography images to load, and I have a NAS that acts as an online backup system. The OpenMediaVault machine is a near-offline counterpart to the NAS for added safety.
Recently, I needed to check on the number of image files in a directory from an SSH session because of a need to create a new repository for 2024. Some files from this year had ended up in the 2023 one, and I needed to be sure that nothing from last year ended in the 2024 folder, or vice versa. Getting a file count from a trusted source was a quick way of doing exactly this.
Due to clumsiness with the NAS, I had to do this using the OpenMediaVault machine. While I could go mounting drives on an interim basis, it was quicker to work from a BASH session. The trick was to use the wc
command for counting the lines output by an invocation of the ls
command. An example follows:
ls -l | wc -l
The -l (as in l
for Lima) switch forces wc
to count lines, while the counterpart (same letter) for ls forces it to list the contents in long form, one item per line. Thus, counting the number of lines gets you the count of the number of files. The call to the ls
command can be customised to add other things life the number of dot files, but the above was enough for my purposes. When the files in both 2023 directories matched, I was satisfied that all was in order.
Installing FreeBSD in a VirtualBox Virtual Machine
2nd March 2014With UNIX being the basis of Linux, I have a soft spot for trying out any UNIX that can be installed on a PC. For a while, I had OpenSolaris on the go and even vaguely recall having a look at one of the BSD’s. However, any recent attempt to install one of the latter, and there are quite a few around now, got stymied by some sort of kernel panic caused by using AMD CPU’s. With the return to the Intel fold arising from the upgrade of my main home PC last year, it perhaps was time to try again.
The recent release of FreeBSD 10.0 was the cue and I downloaded a DVD image for a test installation in a VirtualBox virtual machine with 4 GB of memory and a 32 GB virtual hard drive attached (expanding storage was chosen so not all the allocated space has been taken so far). The variant of FreeBSD chosen was the 64-bit x86 one and I set to installing it in there. Though not as pretty in appearance as those in various Linux distros, the installer was not that user unfriendly to me. Mind you, I have experience of installing Arch Linux so that might have acclimatised me somewhat.
Those installation screens ask about the keyboard mapping that you want and I successfully chose one of the UK options. There was limited opportunity for adding extras though there was a short list of few from which I made some selections. User account set up also was on offer and I would have been better off knowing what groups to assign for my personal user account so as to have to avoid needing to log in as root so often following system start up later. Otherwise, all the default options were sufficient.
When the installation process was complete, it was time to boot into the new system and all that was on offer was a command line log in session. After logging in as root, it was time to press pkg into service in order to get a desktop environment in place. The first step was to install X:
pkg install xorg
Then, it was time to install a desktop environment. While using XFCE or KDE were alternatives, I chose GNOME 2 due to familiarity and more extensive instructions on the corresponding FreeBSD handbook page. Issuing the following command added GNOME and all its helper applications:
pkg install gnome2
So that GNOME starts up at the next reboot, some extra steps are needed. The first of these is to add the following line into /etc/fstab:
proc /proc procfs rw 0 0
Then, two lines were needed in /etc/rc.conf:
gdm_enable=”YES”
gnome_enable=”YES”
The first enables the GNOME display manager and the second activates other GNOME programs that are needed for a desktop session to start. With each of these in place, I got a graphical login screen at the next boot time.
With FreeDSB being a VirtualBox Guest, it was time to consult the relevant FreeBSD manual page. Here, there are sections for a number of virtual machine tools so a search was needed to find the one for VirtualBox. VirtualBox support for FreeBSD is incomplete in that there is no installation media for BSD systems though Linux and Solaris are supported along with Windows. Therefore, it is over to the FreeBSD repositories for the required software:
pkg install virtualbox-ose-additions
Aside from the virtual machine session not capturing and releasing the mouse pointer automatically, that did everything that was needed even if it was the open source edition of the drivers and their proprietary equivalents. To resolve the mouse pointer issue, I needed to temporarily disable the GNOME desktop session in /etc/rc.conf to drop down to a console only session where xorg. conf could be generated using the following commands:
Xorg -configure
cp xorg.conf.new /etc/xorg.conf
In the new xorg.conf file, the mouse section needs to be as follows:
Section “InputDevice”
Identifier “Mouse0”
Driver “vboxmouse”
EndSection
If it doesn’t look like the above and it wasn’t the case for me then it needs changing. Also, any extra lines from the default set up also need removing or the mouse will not function as it should. The ALT+F1 (for accessing GNOME menus) and ALT+F2 (for running commands) keyboard shortcuts then become crucial when your mouse is not working as it should and could avert a panic too; knowing that adjusting a single configuration file will fix a problem when doing so is less accessible is not a good feeling as I discovered to my own cost. The graphics settings were fine by default but here’s what you should have in case it isn’t for you:
Section “Device”
### Available Driver options are:-
### Values: <i>: integer, <f>: float, <bool>: “True”/”False”,
### <string>: “String”, <freq>: “<f> Hz/kHz/MHz”
### [arg]: arg optional
Identifier “Card0”
Driver “vboxvideo”
VendorName “InnoTek Systemberatung GmbH”
BoardName “VirtualBox Graphics Adapter”
BusID “PCI:0:2:0”
EndSection
The next step is to ensure that your HAL settings are as they should. I needed to create a file in /usr/local/etc/hal/fdi/policy called 90-vboxguest.fdi that contains the following:
<?xml version=”1.0″ encoding=”utf-8″?>
<!--
# Sun VirtualBox
# Hal driver description for the vboxmouse driver
# $Id: chapter.xml,v 1.33 2012-03-17 04:53:52 eadler Exp $
Copyright (C) 2008-2009 Sun Microsystems, Inc.
This file is part of VirtualBox Open Source Edition (OSE, as
available from http://www.virtualbox.org. This file is free software;
you can redistribute it and/or modify it under the terms of the GNU
General Public License (GPL) as published by the Free Software
Foundation, in version 2 as it comes in the “COPYING” file of the
VirtualBox OSE distribution. VirtualBox OSE is distributed in the
hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
Clara, CA 95054 USA or visit http://www.sun.com if you need
additional information or have any questions.
-->
<deviceinfo version=”0.2″>
<device>
<match key=”info.subsystem” string=”pci”>
<match key=”info.product” string=”VirtualBox guest Service”>
<append key=”info.capabilities” type=”strlist”>input</append>
<append key=”info.capabilities” type=”strlist”>input.mouse</append>
<merge key=”input.x11_driver” type=”string”>vboxmouse</merge>
<merge key=”input.device” type=”string”>/dev/vboxguest</merge>
</match>
</match>
</device>
</deviceinfo>
With all that set, it is time to ensure that the custom user account is added to the wheel and operator groups using this command:
pw user mod [user name] -G wheel operator
Executing the above as root means that the custom account can run the su command so that logging in as root at the start of a desktop session no longer is needed. That is what being in the wheel group allows and the anyone in the operator group can shut down or restart the system. Both are facilities readily available in Linux so I fancied having them in FreeBSD too.
Being able to switch to root in a terminal session meant that I could go on to add software like Firefox, Libreoffice, GIMP, EMACS, Geany, Netbeans, Banshee and so on. There may be a line of opinion that FreeBSD is a server operating system but all of these make it more than passable for serving as a desktop one too. There may be no package management GUI as such and the ones that come with GNOME do not work either but anyone familiar with command line working will get around that.
FreeBSD may be conservative but that has its place too and being able to build up a system one item at a time teaches far more than getting everything already sorted in one hit. So far, there is enough documentation to get me going and I hope to see where else things go too. So far, the OS hasn’t been that intimidating and that’s good to see.
Getting Adobe Lightroom Classic to remember the search filters that you have set
23rd April 2023With Windows 10 support to end in October 2025 and VirtualBox now offering full support for Windows 11, I have moved onto Windows 11 for personal use while retaining Windows 10 for professional work, at least for now. Of course, a lot could happen before 2025 with rumours of a new Windows version, the moniker Windows 12 has been mooted, but all that is speculation for now.
As part of the changeover, I moved the Adobe apps that I have in an ongoing subscription, Lightroom Classic and Photoshop are the main ones for me, to the new virtual machine. That meant that some settings from the previous one were lost and needed reinstating.
One of those was the persistence of Library Filters, so I had to find out how to get that sorted. If my memory is not fooling me, this seemed to be a default action in the past and that meant that I was surprised by the change in behaviour.
Nevertheless, I had to go to the File menu, select Library Filters (it is near the bottom of the menu in the current version at the time of writing) and switch on Lock Filters by clicking on it to get a tick mark preceding the text. There is another setting called Remember Each Source’s Filters Separately in the same place that can be set in the same manner if so desired, and I am experimenting with that at the moment, even though I have not bothered with this in the past.
Useful Python packages for working with data
14th October 2021My response to changes in the technology stack used in clinical research is to develop some familiarity with programming and scripting platforms that complement and compete with SAS, a system with which I have been programming since 2000. One of these has been R but Python is another that has taken up my attention and I now also have Julia in my sights as well. There may be others to assess in the fullness of time.
While I first started to explore the Data Science world in the autumn of 2017, it was in the autumn of 2019 that I began to complete LinkedIn training courses on the subject. Good though they were, I find that I need to actually use a tool in order to better understand it. At that time, I did get to hear about Python packages like Pandas, NumPy, SciPy, Scikit-learn, Matplotlib, Seaborn and Beautiful Soup though it took until of spring of this year for me to start gaining some hands-on experience with using any of these.
During the summer of 2020, I attended a BCS webinar on the CodeGrades initiative, a programming mentoring scheme inspired by the way classical musicianship is assessed. In fact, one of the main progenitors is a trained classical musician and teacher of classical music who turned to Python programming when starting a family so as to have a more stable income. The approach is that a student selects a project and works their way through it with mentoring and periodic assessments carried out in a gentle and discursive manner. Of course, the project has to be engaging for the learning experience to stay the course and that point came through in the webinar.
That is one lesson that resonates with me with subjects as diverse as web server performance and the ongoing pandemic pandemic supplying data and there are other sources of public data to examine as well before looking through my own personal archive gathered over the decades. Some subjects are uplifting while others are more foreboding but the key thing is that they sustain interest and offer opportunities for new learning. Without being able to dream up new things to try, my knowledge of R and Python would not be as extensive as it is and I hope that it will help with learning Julia too.
In the main, my own learning has been a solo effort with consultation of documentation along with web searches that have brought me to the likes of Real Python, Stack Abuse, Data Viz with Python and R and others for longer tutorials as well as threads on Stack Overflow. Usually, the web searching begins when I need a steer on a particular or a way to resolve a particular error or warning message but books always are worth reading even if that is the slower route. Those from the Dummies series or from O’Reilly have proved must useful so far but I do need to read them more completely than I already have; it is all too tempting to go with the try the “programming and search for solutions as you go” approach instead.
To get going, many choose the Anaconda distribution to get Jupyter notebook functionality but I prefer a more traditional editor so Spyder has been my tool of choice for Python programming and there are others like PyCharm as well. Spyder itself is written in Python so it can be installed using pip from PyPi like other Python packages. It has other dependencies like Pylint for code management activities but these get installed behind the scenes.
The packages that I first met in 2019 may be the mainstays for doing data science but I have discovered others since then. It also seems that there is porosity between the worlds of R an Python so you get some Python packages aping R packages and R has the Reticulate package for executing Python code. There are Python counterparts to such Tidyverse stables as dply and ggplot2 in the form of Siuba and Plotnine, respectively. The syntax of these packages are not direct copies of what is executed in R but they are close enough for there to be enough familiarity for added user friendliness compared to Pandas or Matplotlib. The interoperability does not stop there for there is SQLAlchemy for connecting to MySQL and other databases (PyMySQL is needed as well) and there also is SASPy for interacting with SAS Viya.
Pyhton may not have the speed of Julia but there are plenty of packages for working with larger workloads. Of these, Dask, Modin and RAPIDS all have there uses for dealing with data volumes that make Pandas code crawl. As if to prove that there are plenty of libraries for various forms of data analytics, data science, artificial intelligence and machine learning, there also are the likes of Keras, TensorFlow and NetworkX. These are just a selection of what is available and there is no need not to check out more. It may be tempting to stick with the most popular packages all the time, especially when they do so much, but it never hurst to keep an open mind either.
Getting custom Python imports to work in Visual Studio Code
18th February 2022While I continue to use Spyder as my preferred Python code editor, I also tried out Visual Studio Code. Handily, this Integrated Development Environment also has facilities for working with R and Julia code as well as MarkDown text editing and adding the required extensions is enough for these applications; it helps that there is an unofficial Grammarly extension for content creation.
My Python code development makes use of the Pylance extension and it works a little differently from Spyder when it comes to including files using import statements. Spyder will look into the folder where the base script is located but the default behaviour of Pylance is that it looks in the root path of your workspace. This meant that any code that ran successfully in Spyder failed in Visual Studio Code.
The way around this was to add the required location using the python.analysis.extraPaths setting for the workspace. That meant opening Settings by navigating to File > Preferences > Settings in the menu system and entering python.analysis.extraPaths into the search box. That took me to the section that I needed and I then clicked on Add Item before entering the required path and clicking on the OK button. That was enough to fix the problem and all worked as it should after that.
Getting a Windows 11 Guest to run smoothly on VirtualBox
23rd November 2022In recent days, I have been trying to get Windows 11 to run smoothly within a VirtualBox virtual machine, and there has been a lot of experimentation along the way. This was to eradicate intermittent freezes that escalated CPU usage and necessitated hard restarts. If I was to use Windows 11 as a long-term replacement for Windows 10, these needed to go.
An internet search showed that others faced the same predicament but a range of proposed solutions did nothing for me. The suggestion of enabling 3D graphics capability did nothing but produce a black screen at startup time so that was not a runner. It might have been the combination of underlying graphics hardware and the drivers on my Linux Mint machine that hindered me when it helped others.
In the end, a look at the bug tracker for Windows guest operating systems running on VirtualBox sent me in another direction. The Paravirtualisation interface also may have caused issues with Windows 10 virtual machines since these were all set to KVM. Doing the same for Windows 11 seems to have stopped the freezing behaviour so far. It meant going to the virtual machine settings, navigating to System > Acceleration and changing the dropdown menu value from Default to KVM before clicking on the OK button.
Before that, I have been blaming the newness of VirtualBox 7 (it is best not to expect too much of a fresh release bringing such major changes) and even the way that I installed Windows 11 using the streamlined installation or licensing issues. Now that things are going better, it may have been a lesson from Windows 10 that I had forgotten. The EFI, Secure Boot and TPM 2.0 requirements of Windows 11 also blindsided me, especially given the long wait for VirtualBox to add such compatibility, but that is behind me at this stage.
Windows 11 is not perfect but Start11 makes it usable and the October 2025 expiry for Windows 10 also focuses my mind. It is time to move over for sake of future-proofing if nothing else. In time, we may get a better operating system as Windows 11 matures and some minds surely are thinking of a “Windows 12”. However things go, it may be that we get to a point where something vintage in the nature of Windows XP, Windows 7 or Windows 10 appears. Those older versions of Windows became like old gold during their lives.
Using multi-line commenting in Perl to inactivate blocks of code during testing
26th December 2019Recently, I needed to inactivate blocks of code in a Perl script while doing some testing. This is something that I often do in other computing languages so I sought the same in Perl. To do that, I need to use the POD methodology. This meant enclosing the code as follows.
=start
<< Code to be inactivated by inclusion in a comment >>
=cut
The =start line could use any word after the equality sign but it seems that =cut is needed to close the multi-line comment. If this was actual programming documentation, then the comment block should include some meaningful text for use with perldoc but that was not a concern here since the commenting statements would be removed afterwards anyway and it is good practice not to leave commented code in a production script or program to avoid any later confusion.
In my case, this facility allowed me to isolate the code that I needed to alter and test before putting everything back as needed. It also saved time since I did not need to individually comment out every executable line because multiple lines could be inactivated at a time.
A collection of lessons learnt about web hosting
28th March 2008Putting this blog back on its feet after a spot of web hosting bother caused me to learnt a bit more about web hosting than I otherwise might have done. Here’s a selection and they are in no particular order:
- Store your passwords securely and where you can find them because you never know how a foul up of your own making can strike. For example, a faux pas with a configuration file is all that’s needed to cause havoc for a database site such as a WordPress blog. After all, nobody’s perfect and your hosting provider may not get you out of trouble as quickly as you might like.
- Get a MySQL database or equivalent as part of your package rather than buying one separately. If your provider allows a trial period, then changing from one package to another could be cheaper and easier than if you bought a separate database and needed to jettison it because you changed from, say, a Windows package to a Linux one or vice versa.
- It might be an idea to avoid a reseller unless the service being offered is something special. Going for the sake of lower cost can be a false economy and it might be better to cut out the middleman altogether and go direct to their provider. Being able to distinguish a reseller from a real web host would be nice but I don’t see that ever becoming a reality; it is hardly in resellers’ interests, after all.
- Should you stick with a provider that takes several days to resolve a serious outage? The previous host of this blog had a major MySQL server outage that lasted for up to three days and seeing that was one of the factors that made me turn tail to go to a more trusted provider that I have used for a number of years. The smoothness of the account creation process might be another point worthy of consideration.
- Sluggish system support really can frustrate, especially if there is no telephone support provided and the online ticketing system seems to take forever to deliver solutions. I would advise strongly that a host who offers a helpline is a much better option than someone who doesn’t. Saying all of that, I think that it’s best to be patient and, when your website is offline, that might not be as easy you’d hope it to be.
- Setting up hosting or changing from one provider to another can take a number of days because of all that needs doing. So, it’s best to allow for this and plan ahead. Account creation can be very quick but setting up the website can take time while domain name transfer can take up to 24 hours.
- It might not take the same amount of time to set up Windows hosting as its Linux equivalent. I don’t know if my experience was typical but I have found that the same provider set up Linux hosting far quicker (within 30 minutes) than it did for a Windows-based package (several hours).
- Be careful what package you select; it can be easy to pick the wrong one depending on how your host’s sight is laid out and what they are promoting at the time.
- You can have a Perl/PHP/MySQL site working on Windows, even with IIS being used in place instead of Apache. The Linux/Apache/Perl/PHP/MySQL approach might still be better, though.
- The Windows option allows for ASP, .Net and other such Microsoft technologies to be used. I have to say that my experience and preference is for open source technologies so Linux is my mainstay but learning about the other side can never hurt from a career point of view. After, I am writing this on a Windows Vista powered laptop to see how the other half live as much as anything else.
- Domains serviced by hosting resellers can be visible to the systems of those from whom they buy their wholesale hosting. This frustrated my initial attempts to move this blog over because I couldn’t get an account set up for technologytales.com because a reseller had it already on the same system. It was only when I got the reseller to delete the account with them that things began to run more smoothly.
- If things are not going as you would like them, getting your account deleted might be easier than you think so don’t procrastinate because you think it a hard thing to do. Of course, it goes without saying that you should back things up beforehand.