Avatar billede jensgram Nybegynder
20. juli 2004 - 11:32 Der er 11 kommentarer og
1 løsning

Genkendelse af år, måned og dag. Hvordan?

Hej Eksperter

Da jeg absolut ikke er den store haj til reg-exp vil jeg lige forhøre mig her. Om ikke andet kan det jo være, at Erik kigger forbi ;)

Jeg skal - i forbindelse med et nyhedssystem - have lavet en "parser", der kan genkende en dato. Det er i og for sig ret nemt, og følgende skulle gerne give et indblik i, hvilke mønstre, der skal matches på:

1) Kun årstal: YYYY  =  2000 -> indeværende år (date('Y'))
2) År og måned: YYYY/m  =  [ovenstående]/1 -> 12
3) Fuld dato: YYYY/m/d  = [ovenstående]/1 -> 31

Om datoen er ugyldig (eks. 2004/2/31 (31. feb. ?!?) er underordnet - det kan jeg selv kontrollere bagefter.

Det eneste jeg vil have er et match (ereg eller preg_match - hvad ved jeg?) der indeholder 0-3 elementer:

0: Der var ikke engang et årstal fra mønster 1)
1: Årstal fra mønster 1)
2: Årstal og måned fra mønster 2)
3: Årstal, måned og dag fra mønster 3)

Umiddelbart vil jeg skyde på, at man skal hen i retning af:

ereg('^(([2000-' . date('Y') . '])(\/[1-12](\/[1-31])?)?)?$', $dato, $parts); // kan man overhovedet det med intervaller som [2000-2004] ???
men hvis preg_match er bedre, så er det helt fint. Dem kan jeg bare slet ikke greje.

På forhånd tak
- Jens Gram

PS: Sproget er PHP, hvis nogen skulle være i tvivl (men det er vel ligemeget)

PPS: Hvis man ikke kan lave range's som [2000-2004], så er det ok, at der blot bliver kontrolleret for et 2-tal og et 0 efterfulgt af to tal ( 20[0,9]{2} ) osv.
Avatar billede snepnet Nybegynder
20. juli 2004 - 11:57 #1
Jeg heller ikke ekspert i regulære udtryk, men her er i hvert fald et godt tool :o)
http://royo.is-a-geek.com/iserializable/regulator/

Og der er en kort anmeldelse af det her :
http://msdn.microsoft.com/msdnmag/issues/04/07/MustHaveTools/default.aspx
Avatar billede jensgram Nybegynder
20. juli 2004 - 19:41 #2
Er der ingen hajer herinde?

Om ikke andet må jeg ty til en omgang explode(), som jeg da kan finde ud af ;)
Avatar billede jensgram Nybegynder
20. juli 2004 - 19:42 #3
snepnet > Problemet med ovenstående program (som ser ret godt ud) er, at jeg ikke ved hvor jeg skal starte og slutte med ovennævnte reg.exp...
Avatar billede roenving Novice
21. juli 2004 - 13:17 #4
Den gale ting, jeg kan se i din regexp er den du selv er tvivlende overfor nemlig intervallet, som man ikke kan ...

[2000-2004] betyder nemlig 2, 0, 0, 0-2, 0, 0 eller 4, altså enten 0,1,2 eller 4 ...

-- der er også noget med dine paranteser, som jeg ikke kan gennemskue, men jeg ville så også bruge en replace til at hive værdierne ud, og umiddelbart tror jeg ikke du kan lave det i eet hug, du skal ud i to ...

Men du kan da prøve med:

$parts = preg_replace("^(20\d{2})?(\d|1[0-2])?([1-9]|[12]\d|3[01])?$","$1,$2,$3",$dato);

-- jeg ved faktisk ikke om den vil virke ordentligt, men så har du da et sted at starte ...

-- og da jeg ikke ved så meget om php, er jeg heller ikke klar over, om det skal være en anden replace, f.eks. ereg eller eregi !-)
Avatar billede jensgram Nybegynder
21. juli 2004 - 16:26 #5
roenving > Takker for gennemgangen. Jeg vil springe ud i din reg.exp og se, hvad der kommer ud af det...
Avatar billede roenving Novice
21. juli 2004 - 16:31 #6
-- uden det første spørgsmålstegn bør den slet ikke genkende, så du kan aftaste om der er fejl !-)
Avatar billede jensgram Nybegynder
21. juli 2004 - 16:49 #7
Jeg har testet mig frem:

$cnt = preg_match("/^(20\d{2})(\/([1-9]|1[0-2]))?(\/([1-9]|[12]\d|3[01]))?$/", $dato, $parts);

Giver eksempelvis følgende:

array(6) {
  [0]=>
  string(10) "2024/12/21"
  [1]=>
  string(4) "2024"
  [2]=>
  string(3) "/12"
  [3]=>
  string(2) "12"
  [4]=>
  string(3) "/21"
  [5]=>
  string(2) "21"
}

Det er ok - den overdrevne brug af parenteser skyldes, at jeg så får "pæne" data som eks.  [3]=>
  string(2) "12" i stedet for  [2]=>
  string(3) "/12" som måned.

Tak for hjælpen, roenving. Det hjalp mig på sporet.

Smid et svar.

- Jens Gram
Avatar billede roenving Novice
21. juli 2004 - 17:00 #8
Okay, så velbekomme '-)
Avatar billede jensgram Nybegynder
22. juli 2004 - 22:24 #9
Det er mig der takker
Avatar billede roenving Novice
23. juli 2004 - 09:04 #10
-- og tak for point ;~}
Avatar billede jensgram Nybegynder
23. juli 2004 - 10:57 #11
Jeg rodede videre og denne:

print preg_match('/^(20\d{2})(\/(1[0-2]|[1-9])(\/(3[01]|[12]\d|[1-9]))?)?/', '2004/10/5', $parts);

Kan _lige_ hvad jeg manglede. Den matcher alt hvad jeg kan finde på at give den og returnerer kun de korrekte dele:

ex:

'2004/100/5' => 2004 & 10 (som er det eneste rigtige)

'2004/0/31' => 2004 (igen; den eneste brugbare del)

Rækkefølgen omkring | har åbenbart noget at sige, men du fik lært mig en del, roenving.
Avatar billede roenving Novice
23. juli 2004 - 11:21 #12
Ja, en regexp er som udgangspunkt greedy, det vil sige, at den prøver at finde så lang en match, som overhovedet mulig, så man skal altid teste for den længste mulighed først !-)

Så også jeg fik lige sparket noget ind i baghovedet !o]
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester