# DateTimePicker c# Tage berechnen



## werner_sg (22. Juni 2021)

Hallo zusammen

ich würde gerne die Anzahl der Tage zwischen zwei Daten berechnen, wobei es eigentlich nur noch hängt wenn ein Jahreswechsel besteht.


```
Private Sub DateTimePicker3_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DateTimePicker3.ValueChanged
        Dim days As New Integer
        Dim days2 As New Integer
        Dim days3 As New Integer
        Dim days4 As New Integer

        days = DateTimePicker3.Value.DayOfYear - DateTimePicker1.Value.DayOfYear
        days2 = DateTimePicker3.Value.DayOfYear
        days3 = DateTimePicker1.Value.Day
        days4 = DateTimePicker3.Value.DayOfYear




        TxtAnzahlTage.Text = days.ToString()
        If Val(TxtAnzahlTage.Text) < 0 Then
            TxtAnzahlTage.Text = (31 -days3.ToString() + days4.ToString())
        End If

    End Sub
```

days funktioniert nur innerhalb eines Jahres, von Dezember 2021 auf Januar 2022 ergibt es 0.
in der if Abfrage konnte ich das Problem von Dezember auf die Monate des folge Jahres lösen, in dem ich einfach das Ergebnis von days3 von der Anzahl der Tage im Dezember (31) abziehe und dann die Tage des nächsten Jahres hinzufüge.

ist aber nur eine unbefriedigende Notlösung, da wenn das Startdatum vor Dezember liegt das ganze nicht mehr richtig berechnet wird 
vom 28 September 2021 bis zum 18 Februar gibt es dann das gleiche Ergebnis wie vom 28 Dezember bis zum 18 Februar

Auch eine Variante mit 365 - days2 würde alle 4 Jahre einen fehler aufweisen wegen des Schaltjahres ;-)

Welche Lösung gibt es

Danke Werner


----------



## Zvoni (22. Juni 2021)

Bin kein .NET-ler, aber ich wäre doch sehr überrascht, wenn es in C# keine DateDiff-Funktion gebe (wie ich es aus VBA kenne)


Aber ein Datum (Zeit) lässt sich immer auch als ein Integer (Double) repräsentieren bzw. der Typ DateTime müsste sowieso nur ein Alias/TypeDef für ein Double sein --> 64Bit-Gleitkomma
Nimm das Value des DTPickers, und zieh das eine vom anderen ab

Calculating Date Difference in C#


----------



## Spyke (22. Juni 2021)

einfach die DateTime Objekte subtrahieren

```
TimeSpan ts = DateTimePicker3.Value - DateTimePicker1.Value
```
dies gibt dir ein TimeSpan Objekt zurück und darüber hast du deine Tage

```
ts.TotalDays
```


----------



## Zvoni (22. Juni 2021)

Da war ich doch mal nah dran..


----------



## werner_sg (22. Juni 2021)

Spyke hat gesagt.:


> einfach die DateTime Objekte subtrahieren
> 
> ```
> TimeSpan ts = DateTimePicker3.Value - DateTimePicker1.Value
> ...



Hatte ich bereits versucht dabei erhalte ich die Meldung "Timespan ist ein Strukturtyp und kann nicht als Ausdruck verwendet werden"


----------



## werner_sg (22. Juni 2021)

Zvoni hat gesagt.:


> Bin kein .NET-ler, aber ich wäre doch sehr überrascht, wenn es in C# keine DateDiff-Funktion gebe (wie ich es aus VBA kenne)
> 
> 
> Aber ein Datum (Zeit) lässt sich immer auch als ein Integer (Double) repräsentieren bzw. der Typ DateTime müsste sowieso nur ein Alias/TypeDef für ein Double sein --> 64Bit-Gleitkomma
> ...


funktioniert nur innerhalb eines Jahres bei Verwendung von DateTimePicker3.Value.DayOfYear darüberhinaus muss getrickst werden


----------



## Spyke (22. Juni 2021)

was machst du weiter mit dem TimeSpan?
an der Subtraktion und dem TimeSpan kanns eigentlich nicht liegen


----------



## Zvoni (22. Juni 2021)

Huh?
Ergibt keinen Sinn für mich.
DTPicker.Value sollte ein DateTime sein
How can I convert a DateTime to an int?

Sollte also eine "ticks"-Eigenschaft haben. Die ticks von einander abziehen, und fertig.


----------



## werner_sg (22. Juni 2021)

Zvoni hat gesagt.:


> Huh?
> Ergibt keinen Sinn für mich.
> DTPicker.Value sollte ein DateTime sein
> How can I convert a DateTime to an int?
> ...


für mich ja auch nicht

habs jetzt erst mal so 


```
Private Sub DateTimePicker1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DateTimePicker1.ValueChanged



        Dim days As New Integer
        Dim days2 As New Integer
        Dim days4 As New Integer

        days = DateTimePicker3.Value.DayOfYear - DateTimePicker1.Value.DayOfYear    'berechnet die Anzahl der Tage in einem Jahr
        days2 = DateTimePicker1.Value.DayOfYear                                     ' gibt den Tag des Jahres aus Startdatum
        days4 = DateTimePicker3.Value.DayOfYear                                     ' gibt den Tag des Jahres aus Enddatum




        TxtAnzahlTage.Text = days.ToString()
        If Val(TxtAnzahlTage.Text) < 0 Then                                         'funktioniert innerhalb eines Jahres
            TxtAnzahlTage.Text = (365 - days2.ToString() + days4.ToString())        ' Alternative bei Jahrewechsel wenn kein Schaltjahr
        End If

    End Sub
```

suche jetzt noch eine Lösung die Tage des ganzen Jahres aus Picker3 zu erhalten, dann könnte ich soweit diese dann 366 sind noch mit in die if Einbauen

Gruß Werner


----------



## werner_sg (22. Juni 2021)

Spyke hat gesagt.:


> was machst du weiter mit dem TimeSpan?
> an der Subtraktion und dem TimeSpan kanns eigentlich nicht liegen


nur in einer TextBox ausgeben es klappt ja soweit und mit der Alternativen in der If Anweisung auch bei normalen Jahren nur Schaltjahre würden halt nach dem 28 Februar nicht mehr stimmen


----------



## Zvoni (22. Juni 2021)

Wieso benutzt du DayOfYear?
Ist doch klar, dass damit nur Murks raus kommt


----------



## werner_sg (22. Juni 2021)

Zvoni hat gesagt.:


> Wieso benutzt du DayOfYear?
> Ist doch klar, dass damit nur Murks raus kommt


welche Alternative schlägst du vor, das ist bisher die einzige bis auf Schaltjahre funktionierende Lösung.


----------



## Zvoni (22. Juni 2021)

Entweder Spykes Lösung (und "geht nicht" ist keine Fehlermeldung, hier dann weiter forschen, warum es nicht geht), oder meine "Krücken"-Lösung (entweder über ticks-Eigenschaft) oder hart in Integer bzw. Double casten, und voneinander subtrahieren.

Ich kann mir nicht vorstellen, dass eine "moderne" Sprache wie C# gegenüber vb6/vba so im Nachteil wäre.
In dem einen Link den ich eingehängt habe wird sogar erwähnt den VB.NET-Namespace einzubinden, und deren DateDiff-Funktion zu benutzen

EDIT: Hier ein Beispiel in VBA
Ich habe absichtlich ein Schaltjahr genommen, damit du siehst, dass SchaltJahr automatisch berücksichtigt wird.

```
Sub Irgendwas()
Dim StartDate As Date
Dim EndDate As Date
    StartDate = CDate("28.02.2020")
    EndDate = CDate("01.03.2020")
    Debug.Print "StartDate: " & CLng(StartDate)
    Debug.Print "EndDate: " & CLng(EndDate)
    Debug.Print "DateDiff-Funktion: " & DateDiff("d", StartDate, EndDate)
    Debug.Print "Subtraktion: " & CLng(EndDate) - CLng(StartDate)
End Sub
```

Ergibt:

```
StartDate: 43889
EndDate: 43891
DateDiff-Funktion: 2
Subtraktion: 2
```

EDIT2: Falls du es warum auch immer auf deine Art lösen willst:
Hiermit kannst du herausfinden, ob ein Jahr ein Schaltjahr ist
DateTime.IsLeapYear() Method in C#


----------



## werner_sg (22. Juni 2021)

Zvoni hat gesagt.:


> Entweder Spykes Lösung (und "geht nicht" ist keine Fehlermeldung, hier dann weiter forschen, warum es nicht geht), oder meine "Krücken"-Lösung (entweder über ticks-Eigenschaft) oder hart in Integer bzw. Double casten, und voneinander subtrahieren.
> 
> Ich kann mir nicht vorstellen, dass eine "moderne" Sprache wie C# gegenüber vb6/vba so im Nachteil wäre.
> In dem einen Link den ich eingehängt habe wird sogar erwähnt den VB.NET-Namespace einzubinden, und deren DateDiff-Funktion zu benutzen
> ...


Alle Lösungen funktionierten leider nur innerhalb eines Jahres, also wenn das Anfangsdatum im Jahr 2020 liegt und das Enddatum ebenfalls in 2020 liegt, Probleme gibt es erst wenn der Anfang in 2020 liegt und das Ende in 2021.

Daher habe ich dann solange gesucht und zusammengestellt bis es zumindest ausgenommen der Schaltjahre läuft wobei es immer nur bei Situationen von unterschiedlichem Jahr im Anfang und Ende liegt.

Wobei es aber auch nur von dem Schaltjahr im Anfangsdatum abhängt

Ich werde einfach mal nach deinem Link den ersten TimePicker auf ein Schatjahr prüfen und wenn es eins ist einfach wieder einen Tag der ja dann in der Berechnung zuviel ist wieder abziehen

Also Danke für den Hinweis

Vieleicht kannst du mich aber auch direkt schon mal beim nächsten Punkt in die richtige richtung stoßen

alle Einträge einer Spalte der Tabelle sind über eine TextBox auswählbar, ich möchte aber das alle Einträge vom Datum des ersten TimePickers bis zum Datum des zweiten TimePickers nicht mit angezeigt werden.

mein bisheriger Code dazu

Die Bereitstellung der Daten


```
Try
            dbcmd = New OleDbCommand("SELECT * FROM tblfahrzeuge", conn)
            Dim DbReader As OleDbDataReader

            DbReader = dbcmd.ExecuteReader
            While DbReader.Read
                CboxFahrzeug.Items.Add(DbReader("KFZ_NAME").ToString)
            End While
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
```

Die passende Checkbox dazu


```
Private Sub Cboxcarname_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CboxFahrzeug.SelectedIndexChanged
        conn.Open()

        Try
            dbcmd = New OleDbCommand("SELECT * FROM tblfahrzeuge WHERE KFZ_NAME ='" & CboxFahrzeug.Text & "'", conn)
            Dim DbReader As OleDbDataReader

            DbReader = dbcmd.ExecuteReader
            While DbReader.Read
                Txtfahrzeugkennzeichen.Text = DbReader("KFZ_KENNZEICHEN")
                TxtTagesmiete.Text = DbReader("MIETE_PRO_TAG")
                TxtFahrzeugNummer.Text = DbReader("KFZ_ID")
                Txtkilometer.Text = DbReader("KFZ_KILOMETER")
                TxtTankinhalt.Text = DbReader("KFZ_TANK")
                TxtStandort.Text = DbReader("KFZ_STANDORT")

            End While
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try


        conn.Close()
    End Sub
```

Die Select Anweisung müsste irgendwie wie folgt aussehen


```
dbcmd = New OleDbCommand("SELECT * FROM tblfahrzeuge WHERE KFZ_NAME ='" & CboxFahrzeug.Text & "'" AND NOT zwischen Picker1 und Picker3", conn)
```


----------



## Zvoni (22. Juni 2021)

Such mal nach SQL NOT BETWEEN
btw: Einen SQL-String wie oben zusammenzubauen ist "bad practice".
Lieber Parameter benutzen, in welchem Falle du dann auch den ganzen Schmarrn mit Anführungszeichen für Strings usw. komplett weglassen kannst, weil es die Engine für dich dann macht.
Wie gesagt: Bin kein .NET-ler, aber ich glaube mich daran zu erinnern, dass sowas wie StringBuilder angeboten wird in .NET


----------



## werner_sg (22. Juni 2021)

```
Private Sub DateTimePicker3_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DateTimePicker3.ValueChanged
        Dim days As New Integer
        Dim days2 As New Integer
        Dim days3 As New Integer
        Dim JahresZahl As New Integer

        days = DateTimePicker3.Value.DayOfYear - DateTimePicker1.Value.DayOfYear
        days2 = DateTimePicker1.Value.DayOfYear
        days3 = DateTimePicker3.Value.DayOfYear
        JahresZahl = DateTimePicker1.Value.Year




        TxtAnzahlTage.Text = days.ToString()
        If Val(TxtAnzahlTage.Text) < 0 Then
            TxtAnzahlTage.Text = (365 - days2.ToString() + days3.ToString())
        End If

        Try

            If (JahresZahl / 4 = 0 & JahresZahl / 100 = 0) Then     ' prüft auf Schaltjahr

                TxtAnzahlTage.Text = (TxtAnzahlTage.Text + 1)        ' ist Schaltjahr wird ein Tag dazu gezählt


            End If

        Catch ex As Exception

        End Try

    End Sub
```

So klappt es einwandfrei, Danke an alle für die Mithilfe


----------



## werner_sg (22. Juni 2021)

Zvoni hat gesagt.:


> Such mal nach SQL NOT BETWEEN
> btw: Einen SQL-String wie oben zusammenzubauen ist "bad practice".
> Lieber Parameter benutzen, in welchem Falle du dann auch den ganzen Schmarrn mit Anführungszeichen für Strings usw. komplett weglassen kannst, weil es die Engine für dich dann macht.
> Wie gesagt: Bin kein .NET-ler, aber ich glaube mich daran zu erinnern, dass sowas wie StringBuilder angeboten wird in .NET


Danke der Hinweis ist gut werde das mal angehen mit NOT BETWEEN

Das der Beispiel String für die Katz war ist mir klar, war nur zur vereinfachten Erklärung was ich suchte, BETWEEN hatte ich nicht auf dem Schirm, braucht man ja auch wirklich nur sehr selten (ich zumindest)


----------



## Spyke (22. Juni 2021)

Zvoni hat gesagt.:


> Ich kann mir nicht vorstellen, dass eine "moderne" Sprache wie C# gegenüber vb6/vba so im Nachteil wäre.
> In dem einen Link den ich eingehängt habe wird sogar erwähnt den VB.NET-Namespace einzubinden, und deren DateDiff-Funktion zu benutzen



Geht unter C# auch relativ einfach, was mich hier verwundert.
Hier wird ja mit VB.Net programmiert.

Das es anscheinend unter VB.Net geht einen int Wert mit einem string zu subtrahieren.

```
TxtAnzahlTage.Text = (365 - days2.ToString() + days3.ToString())
```
unter C# geht sowas nicht, da meckert das direkt der Compiler an
da müsst man sowas z.B. schreiben

```
TxtAnzahlTage.Text = (365 - days2 + days3).ToString()
```

Vielleicht gibts für VB.Net Einschränkungen das es da mit TimeSpan nicht funktioniert, gibt ja nicht umsonst den VisualBasic namespace


----------



## Zvoni (22. Juni 2021)

Spyke hat gesagt.:


> Geht unter C# auch relativ einfach, was mich hier verwundert.
> *Hier wird ja mit VB.Net programmiert.*
> *schnipp*


Wie kommst du denn da drauf?
Im Subject des Threads sehe ich eindeutig ein "c#"


----------



## Spyke (22. Juni 2021)

Zvoni hat gesagt.:


> Wie kommst du denn da drauf?
> Im Subject des Threads sehe ich eindeutig ein "c#"


Am Quellcode, der VB.Net Syntax ;-)


----------



## werner_sg (22. Juni 2021)

Spyke hat gesagt.:


> Am Quellcode, der VB.Net Syntax ;-)


Da hast Du vollkommen recht, bin etwas neben der Spur
hab mir vor 3 Wochen einen Nerv unter dem Rippenmuskel eingeklemmt und mach das gerade zugedröhnt mit Schmerzmitteln, war etwas im falschen Film dabei


----------

