Tips en Trucs 2020

Werken met datums in Bash scripts

Werken met datums in een script of programma is steeds een uitdaging. Zo gebruikt elke programmeertaal wel eigen bibliotheken om met datums en tijden te werken. Daarenboven werkt elk besturingssysteem met een eigen referentiepunt (Zie Unix Epoch op Wikipedia). Bestaat er dan niet zoiets als een universele manier van werken met datums in programma's. De eenvoudigste manier van werken blijft bestaan uit het gebruik van datums en tijden in tekstvorm volgens de internationale standaarden. Je kunt deze notatie bekijken met de opdracht:

dany@pindabook:~> LC_ALL=C date -u
Sat May 16 08:04:16 UTC 2020

De omgevingsvariabele LC_ALL zorgt dat de datum volgens de US standaard in het Engels wordt weergegeven. De -u optie bij de date opdracht zorgt dat we de UTC tijd gebruiken. De UTC tijd heeft in de zomer bij ons een tijdsverschil van 2 uur. Maar het rekent gemakkelijker.

Wil je de datum van een bepaalde kalenderdag weergeven, kan je dit opvragen met een date optie:

dany@pindabook:~> date -u --date "march 18 2020"
wo 18 mrt 2020  0:00:00 UTC

Je merkt dat zonder de omgevingsvariabele LC_ALL de taal en datuminstellingen van uw systeem gebruikt worden. Riskant als uw script op een andere computersysteem wordt uitgevoerd. Wie liever met klassieke datumnotaties werkt, kan ook gebruik maken van:

dany@pindabook:~> date -u --date "2020-03-18"
wo 18 mrt 2020  0:00:00 UTC

Vanzelfsprekend kan je alle mogelijke date opties opzoeken in de man pagina van date:

dany@pindabook:~> man date
Man: alle passende pagina's vinden, niet alleen eerste (set MAN_POSIXLY_CORRECT to avoid this)
 * date (1)
   date (1p)
Man: Welke man-pagina wilt u zien?
Man:

Druk Enter om de manual met het sterretje te bekijken. De man pagina verlaat je met een druk op de q toets (Quit).

man date

Handig, maar rekenen kan je met tekst niet. Zo wordt het moeilijk om bijvoorbeeld vandaag binnen veertien dagen aan te duiden. Daarvoor converteren we datums en tijden naar gehele getallen. Het geheel getal stelt in Linux (Unix) de tijd in seconden voor die verlopen is sedert 00:00:00 GMT op 1 januari 1970. Aangezien je een 32-bits geheel getal terugkrijgt, krijgen we vanaf 19 januari 2038 om 03:14:08 UTC een probleem (zie Softwareprobleem jaar 2038 op Wikipedia). Als je echter met tekstnotaties werkt, zoals hier beschreven, heb je daar weinig last van. De systemen zullen tegen dan reeds lang aangepast zijn en bijvoorbeeld 64-bits gehele getallen gebruiken. De omzetting van datum naar geheel getal kan je ook met de date opdracht uitvoeren:

dany@pindabook:~> date -u +%s
1589619994
dany@pindabook:~> date -u --date "2020-03-18" +%s
1584489600

Deze waarde kan je in een variabele opslaan, om er later berekeningen mee uit te voeren:

dany@pindabook:~> vandaag=$(date -u +%s)
dany@pindabook:~> echo $vandaag
1589620199

Een dag bevat 24 uur, een uur bevat 60 minuten en een minuut 60 seconden, dan bevat een dag 24 x 60 * 60 = 86400 seconden. Morgen wordt dan:

dany@pindabook:~> morgen=$((vandaag + 86400))

Om de datum op middernacht af te ronden, gebruiken we de bewerking modulus (%, rest na deling):

dany@pindabook:~> morgen=$((morgen - (morgen % 86400)))

Wordt:

dany@pindabook:~> date -u --date @$morgen
zo 17 mei 2020  0:00:00 UTC

Het apestaartje zorgt dus voor de conversie van geheel getal (seconden) naar een datum in tekstvorm.

Script om volgende herhalende afspraakdatum te bepalen

Het volgende script berekent op basis van een begindatum ($recevent) en tussentijd ($timebetween) de volgende afspraakdatum.

#!/bin/bash
# Geef de Universele datum en tijd weer als een geheel getal
now=$(date -u +%s)
# We zijn enkel geïnteresseerd in de datum, een dag bevat 86400 seconden
today=$((now - (now % 86400)))
# Geef de Universele datum en tijd van 18 maart weer als een geheel getal
recevent=$(date -u --date "2020-03-18" +%s)
# Om de veertien dagen
timebetween=$((14 * 86400))
echo "                 Vandaag: $(date -u --date @$today) ($today)"
echo "   Terugkerende afspraak: $(date -u --date @$recevent) ($recevent)" 
echo "Tijd tussen de afspraken: $((timebetween / 86400)) dagen"
# Zoek naar de volgende afspraak
while  [ $recevent -lt $today ]; do
  recevent=$((recevent + timebetween))
done
echo "       Volgende afspraak: $(date -u --date @$recevent)"

Bij het uitvoeren van het script krijg je de volgende uitvoer:

dany@pindabook:~> sh afspraak.sh
                 Vandaag: za 16 mei 2020  0:00:00 UTC (1589587200)
   Terugkerende afspraak: wo 18 mrt 2020  0:00:00 UTC (1584489600)
Tijd tussen de afspraken: 14 dagen
       Volgende afspraak: wo 27 mei 2020  0:00:00 UTC

Kleuren in de teksteditor nano

Iedereen heeft zijn eigen voorkeur wat betreft teksteditors. Sommigen gebruiken graag een grafische editor, anderen enkel terminal editors. Onder zowel de grafische als terminal editors heb je nog een zeer groot aanbod van editors. En een mens zoekt al snel iets dat standaard op verschillende systemen gebruikt kan worden. Zo gebruik ik standaard op de Raspberry Pi nano, maar openSUSE is eerder voorstander van joe. Hoewel nano standaard aanwezig is op elke openSUSE installatie, merk je al vlug dat deze niet optimaal geconfigureerd is. Zo ontbreekt het gebruik van kleuren. Dit los je snel op met de volgende opdracht:

dany@pindabook:~> echo 'include /usr/share/nano/*' >> ~/.nanorc

Let op de enkele aanhalingstekens, deze zijn echt wel noodzakelijk om het sterretje letterlijk als een sterretje in het nano configuratiebestand te krijgen. En dit wordt het resultaat:

Nano kleuren