fredag den 21. oktober 2016

Lidt om datoer (i makro)

I makroen hvor vi importerede CSV-filen ved at indlæse linje for linje, anvendte vi the_cell.Value = [datoværdi]. Lad os kigge lidt mere på, hvordan datoer håndteres i LibreOffice i makroer.

Vi skal se dato-format problemet i to perspektiver:
1) Datoformatet i variable i makroen
2) Datoen, når den indsættes i eller læses fra en celle.

Det er vigtigt at skelne tydeligt mellem de to perspektiver, da resultatet ellers kan vise sig overraskende (forkert).

Denne artikel omhandler første punkt, nemlig håndtering og bearbejdning af datoer med makroer. Datofunktionerne er ikke afhængige af Calc, men fungerer også med datoer i f.eks. Writer.

I makroen, når vi arbejder med datoer i variable, kan vi tænk på datoer som to forskellige typer tekst: En lokaliseret (dansk, engelsk, ...) version og en international version (ISO 8601 date format). I bund og grund fungerer begge typer fuldstændig uden problemer, men lokaliseret dato er standard, og ISO 8601 (YYYY-MM-DD) er kun relevant, når vi vælger det eksplicit.

Ikke desto mindre regner LibreOffice med en intern dato-værdi, hvor 0 svarer til 29/12/1899: -1
30/12/1899: 0
31/12/1899: 1
01/01/1900: 2
01/02/1900: 3
01/01/2001: 36892

Datokonvertering:
  • CDate: Konverter et tal (datoværdi) eller en tekst til en dato.
  • DateValue: Konverterer en formateret tekst (i intervallet 1. december 1, 1582 til 31 December 9999) til en dato-værdi, som ikke har tidsinformationer. Datoen 1. december 1582 svarer ca. til det tidspunkt, hvor den gregorianske kalender blev indført. Se https://da.wikipedia.org/wiki/Gregorianske_kalender
  • CDateFromIso: Konverterer til en dato fra en ISO 8601-dato.
  • CDateToIso: Konverterer en dato til en ISO 8601-dato.
  • IsDate: Er teksten korrekt formateret som dato? Brug IsDate til at afprøve om en tekst indeholder en korrekt formateret dato.
Datoer lige omkring 30/12 1899 kan udløse fejl i tidligere versioner af LibreOffice, men det burde ikke være et problem i nyere versioner.

Når vi så har en dato(værdi), kan vi udlede nogle interessante informationer:
  • Year(date): Returnerer årstallet af en dato som et heltal.
  • Month(date): Returnerer månedsnummeret af en dato som et heltal.
  • Day(date): Returnerer dagstallet af en dato som et heltal.
  • WeekDay(date): Returnerer et heltal fra 1 til 7, som svarer til dage i ugen (søndag til lørdag).
Eksempel
Sub test
my_date=DateValue("19 Januar 1965")
Print isDate(my_date) 'True
Print my_date         '19/01/1965
Print year(my_date)   '1965
End sub


Funktionen DatePart gør noget lignende, nemlig udleder en konkret information
Print DatePart("yyyy",my_date) 'Årstal
Print DatePart("q",my_date)    'Kvartal
Print DatePart("m",my_date)    'Måned
Print DatePart("y",my_date)    'dag i året
Print DatePart("w",my_date)    'Ugedag
Print DatePart("d",my_date)    'Dag


DatePart splitter altså en dato ad i enkeltdele, og vi har en tilsvarende funktion til at samle delene i en dato igen:
Print DateSerial(1965, 1, 19)  '19/01/1965

Vær opmærksom på at DateSerial har en fejl, som betyder at datoen før år 100 konverteres forkert, idet der lægges 1900 til årstallet:
Print DateSerial(90, 1, 19)    '19/01/1990

Vi kan manipulere datoen med funktionen DateAdd sådan:
DateAdd("d", 3, my_date)       'Læg tre dage til datoen
DateAdd("m", 3, my_date)       'Læg 3 måneder til datoen
DateAdd("yyyy", -3, my_date)   'Træk 3 år fra datoen


DateDiff anvender tilsvarende tekstparameter til at formatere svaret fra en subtraktion:
my_date=DateValue("19 Januar 1965")
Print DateDiff("yyyy", my_date, Date)  'Jeg er 51 år
Print DateDiff("d",    my_date, Date)  'Mere præcist 18903 dage