FormatException: Tekenreeks is ongeldige Datetime

Pagina: 1
Acties:

Onderwerpen

Vraag


Acties:
  • 0 Henk 'm!

  • Bas..
  • Registratie: Januari 2021
  • Laatst online: 07-03-2022
Mijn vraag
Waarom wordt Datum wel geconverteerd en Datumdier niet ?

Relevante software en hardware die ik gebruik
VisualStudio

Wat ik al gevonden of geprobeerd heb
Bij het uitlezen van een reader zet ik met C# de gegevens om in een json string.
De taak Aanvoer in de reader kent twee datumvelden. Als ik deze in een string weergeef binnen mijn json zie ie er als volgt uit.
Zie veld Datum en veld Datumdier
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[
  {
    "Worpregistratie": [],
    "Doodgeboren": [],
    "Groepsgeboorte": [],
    "Verplaatsing": [],
    "Spenen": [],
    "Afvoer": [],
    "Aanvoer": [
      {
        "Datum": "09012021",
        "Ubn": "6250036",
        "RasId": "77",
        "HokId": "",
        "Lammeren": [
          {
            "Levensnummer": "100211628284",
            "Datumdier": "10102020",
            "Geslacht": "0",
            "ActId": "3",
            "Gewicht": 0.0
          }
        ]
      }
    ],
    "Omnummeren": [],
    "Medicaties": [],
    "Halsnummers": []
  }


Als ik deze velden omzet naar een DateTime? wordt het veld Datum wel geconverteerd maar op het veld Datumdier krijg ik de foutmelding : System.FormatException: 'De tekenreeks is niet als geldige DateTime herkend.'

Class AanvoerReader ziet er zo uit
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 class AanvoerReader : BaseParser
    {
        public List<Aanvoer> ParseArray(string raw)
        {
            List<Aanvoer> aanvoer = new List<Aanvoer>();

            string[] regels = raw.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

            foreach (string regel in regels)
            {
                if (string.IsNullOrEmpty(regel.Replace("\r", ""))) { continue; }

                aanvoer.Add(ParseArr(regel));
            }
            return aanvoer;
        }
        private Aanvoer ParseArr(string raw)
        {
            string[] velden = raw.Split('|');

            Aanvoer aanvoer = new Aanvoer
            {
                Datum = ParseDatum1(velden[1]),
                Ubn = velden[2],
                RasId = velden[3],
                HokId = velden[4],
                Lammeren = ParseLammeren(velden)
            };
            return aanvoer;
        }
        private List<AanvoerLam> ParseLammeren(string[] velden)
        {
            List<AanvoerLam> lammeren = new List<AanvoerLam>();

            int numberOfLamFields = 6;
            for (int l = 0; l < 7; l++)
            {
                int fieldIndex = 6 + l * numberOfLamFields;

                    AanvoerLam lam = new AanvoerLam()
                    {
                        Levensnummer = ParseLevensnummer(velden[fieldIndex], velden[fieldIndex + 1]),                    
                        Datumdier = ParseDatum1(velden[fieldIndex + 2]),
                        Geslacht = velden[fieldIndex + 3],
                        ActId = velden[fieldIndex + 4],
                        Gewicht = ParseGram(velden[fieldIndex + 5])
                    };

                    if (!lam.IsEmpty())
                    {
                        lammeren.Add(lam);
                    }
            }

            return lammeren;
        }
    }

De functie ParseDatum1() ziet er zo uit;
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
protected DateTime? ParseDatum1(string veld)
        {
            DateTime? datum = null;

            if (veld != null)
            {
                return DateTime.ParseExact(veld, "ddMMyyyy", CultureInfo.InvariantCulture);
            }
            else
            {
                return datum.GetValueOrDefault();
            }
        }

Waarom wordt Datum wel geconverteerd en Datumdier niet ?

[ Voor 0% gewijzigd door RobIII op 09-01-2021 16:27 . Reden: Syntax highlighting toegepast ]

Alle reacties


Acties:
  • 0 Henk 'm!

  • Rowwan
  • Registratie: November 2000
  • Laatst online: 20:36
Heb je al gedebugged? Print eens eens inhoud van 'velden[fieldIndex + 2]'

Acties:
  • 0 Henk 'm!

  • Bas..
  • Registratie: Januari 2021
  • Laatst online: 07-03-2022
De foutmelding heeft blijkbaar geen betrekking op "Datumdier": "10102020" maar op de volgende 6 lammeren die geen waarde hebben bij Datumdier. Er kunnen immers per aanvoer max 7 lammeren worden ingescand.
Een lam moet ook zonder Datumdier kunnen worden aangevoerd. Dit is nl. de geboortedatum optioneel.

Een null waarde heb ik juist mogelijk willen maken met ParseDatum1(). Blijkbaar accepteert mijn code nog steeds geen null waarde bij converteren naar DateTime? type.

Wat doe ik fout ?

[ Voor 11% gewijzigd door Bas.. op 09-01-2021 15:29 ]


Acties:
  • 0 Henk 'm!

  • Rowwan
  • Registratie: November 2000
  • Laatst online: 20:36
Je doet vanalles fout :). Je gaat er vanuit dat je altijd 7 lammeren hebt, terwijl je er nu maar één hebt. De fieldindex wijst dus naar rommel.

Enkele tips:
- plaats je code tussen code tags, dan kunnen we ook lezen wat er staat.
- heb je al gedebugged?
- waarom gebruik je geen bestaande JSON parser? (E.g. van newtonsoft)

[ Voor 3% gewijzigd door Rowwan op 09-01-2021 15:33 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Wat @Rowwan zegt: begin eens met Debuggen: Hoe doe ik dat?, of, specifieker voor C#: deze tutorial ;)

Verder heb ik je post aangepast zodat de JSON leesbaar is en de syntax-highlighting voor C# gebruikt wordt. Zie code tags.

Tot slot: doe jezelf een lol en zorg dat je engelstalige foutmeldingen krijgt; dat googled duizend keer makkelijker.

[ Voor 72% gewijzigd door RobIII op 09-01-2021 16:36 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Waarom zijn je datum velden niet in ISO 8601 formaat?
Zover ik weet is dat de enige standaard voor JSON.

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • Bas..
  • Registratie: Januari 2021
  • Laatst online: 07-03-2022
O.b.v. een breakpoint volg ik stap voor stap de code en variabele met bijbehorende waardes. Daar zag ik niets vreemds. Ik heb een light version van Visual Studio dus niet alle mogelijkheden om te debuggen verwacht ik. Watch, Autos en locals heb ik bijvoorbeeld niet helaas.

Ik gebruik Newtonsoft.Json; en de datumformaten worden zo gepresenteerd "Datumdier": "2021-01-09T00:00:00"
ISO 8601 formaat dus

Van elk lam dat wordt gescand is minimaal het geslacht bekend. Vanaf nu lees ik enkel de lammeren waarvan een geslacht bestaat. Op deze manier loop ik alleen het aantal gescande lammeren door.
Wellicht is er een betere oplossing maar dit werkt.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private List<AanvoerLam> ParseLammeren(string[] velden)
        {
            List<AanvoerLam> lammeren = new List<AanvoerLam>();

            int numberOfLamFields = 6;
            for (int l = 0; l < 7; l++)
            {
                int fieldIndex = 6 + l * numberOfLamFields;
                var geslacht = velden[fieldIndex + 3];
                if (geslacht.Length > 0)
                {
                    AanvoerLam lam = new AanvoerLam()
                    {
                        Levensnummer = ParseLevensnummer(velden[fieldIndex], velden[fieldIndex + 1]),
                        Datumdier = ParseDatum1(velden[fieldIndex + 2]),
                        Geslacht = geslacht,
                        ActId = velden[fieldIndex + 4],
                        Gewicht = ParseGram(velden[fieldIndex + 5])
                    };

                    if (!lam.IsEmpty())
                    {
                        lammeren.Add(lam);
                    }
                }
            }

            return lammeren;
        }

Datumdier is dus de geboortedatum en optioneel. Als de geboortedatum niet wordt gepasseerd is Datumdier null. Als de geboortedatum wordt genegeerd/overgeslagen is de waarde van Datumdier "00000000"
Bij zowel null als "00000000" krijg ik nu "Datumdier": "0001-01-01T00:00:00" Is dit de weergave voor
C#:
1
 return datum.GetValueOrDefault(); 
? Zo ja dan is
C#:
1
 && veld != "00000000" 
hier overbodig.
Ik had gehoopt op "Datumdier": "" als resultaat in mijn json.

De code in mij eerste post heb ik als volgt aangepast.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
protected DateTime? ParseDatum1(string veld)
        {
            DateTime? datum = null;

            if (veld.Length > 0 && veld != "00000000")
            {
                return DateTime.ParseExact(veld, "ddMMyyyy", CultureInfo.InvariantCulture);
            }
            else
            {
                return datum.GetValueOrDefault();
            }
        }


De foutmeldingen heb ik gelukkig opgelost. Dank daarvoor.

[ Voor 0% gewijzigd door RobIII op 10-01-2021 12:27 . Reden: Again; syntax-highlighting toegepast ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
DJMaze schreef op zaterdag 9 januari 2021 @ 19:11:
Waarom zijn je datum velden niet in ISO 8601 formaat?
Zover ik weet is dat de enige standaard voor JSON.
JSON specificeert geen datum formaat.
Bas.. schreef op zondag 10 januari 2021 @ 12:07:
Ik heb een light version van Visual Studio dus niet alle mogelijkheden om te debuggen verwacht ik. Watch, Autos en locals heb ik bijvoorbeeld niet helaas.
Je bedoelt de Community versie? Daar zitten iig de door jou genoemde zaken volgens mij gewoon in. Start met debuggen en ga naar Debug -> Windows en dan moet je ze daar gewoon zien.

Verder zou ik als ik jou was eens kijken naar TryParseExact (dan krijg je zoiets) en geef je functie eens een fatsoenlijke naam i.p.v. ParseDatum1 ;)

[ Voor 58% gewijzigd door RobIII op 10-01-2021 12:41 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Rowwan
  • Registratie: November 2000
  • Laatst online: 20:36
Is het probleem nu opgelost?

Ik zie dat je nog steeds 7x lammeren probeert te parsen. Als je er maar één hebt, klopt nog steeds de fieldindex niet.

Verder zeg je dat je newtonsoft gebruikt, maar wat gebruik je dan precies? Je bent nog steeds zelf de data aan het parsen. (Kijk eens naar de Deserialize functie)

De beste manier van debuggen is overigens nog steeds vaak 'console.writeline' :)

[ Voor 12% gewijzigd door Rowwan op 10-01-2021 13:58 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Rowwan schreef op zondag 10 januari 2021 @ 13:56:


Verder zeg je dat je newtonsoft gebruikt, maar wat gebruik je dan precies? Je bent nog steeds zelf de data aan het parsen. (Kijk eens naar de Deserialize functie)
Zoals ik het begrijp parsed TS een EDI bestand (soort van CSV). (Ik vermoed EDI-slacht, heb (lang geleden) ook in dat wereldje gezeten). Volgens mij gebruikt TS Newtonsoft JSON alleen om een object te dumpen.
Rowwan schreef op zondag 10 januari 2021 @ 13:56:

De beste manier van debuggen is overigens nog steeds vaak 'console.writeline' :)
Tenzij je om e.o.a. reden geen gebruik kunt maken van VS is "vaak" een behoorlijk overstatement. We leven niet meer in de oertijd :X

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • labee
  • Registratie: November 2002
  • Laatst online: 10-09-2022
Gebruik altijd TryParse varianten bij het vertalen van string naar een ander type (is sneller).

Voorbeeld:

code:
1
2
3
4
5
if (DateTime.TryParseExact(StringValue, new string[] { "yyyy-MM-dd", "dd-MM-yyyy" }, 
    CultureInfo.CurrentCulture, DateTimeStyles.None, out DateTime dtValue))
{
    return dtValue;
}

[ Voor 9% gewijzigd door labee op 10-01-2021 15:06 ]

http://www.labee.nl


Acties:
  • 0 Henk 'm!

  • Bas..
  • Registratie: Januari 2021
  • Laatst online: 07-03-2022
Het probleem is inderdaad opgelsot :)

Met ASCII lees ik de reader uit. Ik kan ook data met ASCII inlezen. Het gaat nu om het uitlezen van taken. In dit geval de taak Aanvoer.
Elke aanvoer levert een string op met waardes (of niet) die zijn gescheiden door pipelines '|'
De eerste 5 posities zeggen iets over de aanvoer in het algemeen. De eerste positie is de keuze uit 3 mogelijkheden hoe uitgebreid de aanvoer is gescand. Positie 2 t/m 5 zie json in mijn eerste post. Elke volgende 6 posities zijn gegevens van het lam. Max 7 lammeren, dus vanaf positie 6 zijn 42 posities gereserveerd voor een lam.
Het levensnummer staat of op de 1e of op de 2e positie van de 6 posities per lam.

I.p.v. de loop 7 keer te doorlopen zou ik het aantal lammeren kunnen tellen. Dit o.b.v. het levensnummer (al dan niet op positie 1 of 2 van de 6 posities per lam) of het aantal geslachten te tellen. Dit wordt nl. altijd vastgelegd per lam.
Is dat wat je bedoeld Rowwan?

Acties:
  • 0 Henk 'm!

  • Bas..
  • Registratie: Januari 2021
  • Laatst online: 07-03-2022
labee jouw voorstel werkt ook. Dank je wel.
code:
1
 return datum.GetValueOrDefault();
heb ik inmiddels vervangen door
code:
1
 return datum;

Nu krijg ik "Datumdier": null, waar de datum niet bekent is :)
Hiermee is mijn probleem helemaal opgelost. Dank jullie wel allemaal.

Acties:
  • 0 Henk 'm!

  • Rowwan
  • Registratie: November 2000
  • Laatst online: 20:36
Is dat wat je bedoeld Rowwan?
Nee, eigenlijk niet. Maar blijkbaar is je input ook iets anders dan de JSON string. Als je maar één lam hebt, dan is je input dus iets met '|||||||||'?

Acties:
  • 0 Henk 'm!

  • Bas..
  • Registratie: Januari 2021
  • Laatst online: 07-03-2022
Ja klopt Rowwan. De json string is eigenlijk het eindresultaat dat ik naar mijn website stuur.
Pagina: 1