Funktion: Berechnung WeekOfDay

OP #7380116
Lesenswert?

Guten Morgen,

für meine Anwendung benötige ich eine Funktion, mit dieser ich den genauen Wochentag ermitteln kann. Als Eingabe wird ein string übergeben:

1
char *Date = "2023-03-20";

Im Netz habe ich schon die ein oder andere Funktion gefunden und auch getstet. Leider waren diese Funktionen nicht korrekt, was die Ausgabe betraf. Gibt es eventuell hier im FOrum jemand der bereits so eine Funktion schon entwickelt hat?

#7380133
Lesenswert?

Mit den Funktionen aus <time.h> und etwas drum herum kann man das machen. Jahr, Monat, Tag mit sscanf aus dem String lesen.

struct tm füllen, in Epoch umwandeln mit mktime() und damit über localtime() eine (jetzt richtig gefüllte) struct tm beschreiben.

Im Member tm_wday steht dann der Wochentag (Sonntag = 0)

Wenn man nur den Text braucht, geht dann auch gleich strftime()

#7380142
Lesenswert?

Quick&Dirty. Verlässt sich voll auf ein gültiges, ISO 8601-Formatiertes Datum im input.

1
#include <stdint.h>
2
#include <time.h>
3
#include <string.h>
4
#include <stdlib.h>
5

6
int dow(const char * date) {
7
    struct tm myTime;
8
    memset (&myTime, '\0', sizeof (myTime));
9
    myTime.tm_year = atoi(date);
10
    myTime.tm_mon = atoi(date+5)-1;
11
    myTime.tm_mday = atoi(date+8);
12
    mktime(&myTime);
13
    return myTime.tm_wday;
14
}

Statt den drei "atoi"-Zeilen geht evtl. auch ein strptime(date, "%F", myTime);

#7380151
Lesenswert?

1
#include <stdio.h>
2
#include <time.h>
3

4
int main (){
5
  struct tm timeinfo = *localtime(&(time_t){time(0)});
6
  printf("%.2s\n", &"SoMoDiMiFrSa"[timeinfo.tm_wday*2]);
7
  return 0;
8
}

Die Funktionen kannst du dir in musl libc nachsehen, wie die implementiert sind: https://git.musl-libc.org/cgit/musl/tree/src/time/

Die Aktuellen Zeitzohnendaten kriegt man bei IANA: https://www.iana.org/time-zones

Aber vielleicht reicht ja schon der Teil: http://git.musl-libc.org/cgit/musl/tree/src/time/__secs_to_tm.c

Beitrag #7380161 wurde von einem Moderator gelöscht.
#7380168
Lesenswert?

Mein Fehler: "Year minus 1900" fehlt im Code. Da steht aber auch die Erklärung für "Monat-1".

1
       struct tm {
2
           int         tm_sec;    /* Seconds          [0, 60] */
3
           int         tm_min;    /* Minutes          [0, 59] */
4
           int         tm_hour;   /* Hour             [0, 23] */
5
           int         tm_mday;   /* Day of the month [1, 31] */
6
           int         tm_mon;    /* Month            [0, 11]  (January = 0) */
7
           int         tm_year;   /* Year minus 1900 */
8
           int         tm_wday;   /* Day of the week  [0, 6]   (Sunday = 0) */
9
           int         tm_yday;   /* Day of the year  [0, 365] (Jan/01 = 0) */
10
           int         tm_isdst;  /* Daylight savings flag */
11

12
           long        tm_gmtoff; /* Seconds East of UTC */
13
           const char *tm_zone;   /* Timezone abbreviation */
14
       };

Sonntag wäre 0, nicht 7.

OP #7380175
Lesenswert?

Nun stimmt es. Ich habe in der Funktion noch year - 1900 berechnet.

1
int dow(const char * date)
2
{
3

4
    struct tm myTime;
5

6
    memset (&myTime, '\0', sizeof (myTime));
7

8
    myTime.tm_year = atoi(date)-1900;
9
    myTime.tm_mon = atoi(date+5)-1;
10
    myTime.tm_mday = atoi(date+8);
11

12
    mktime(&myTime);
13

14
    return myTime.tm_wday;
15

16
}
OP #7380874
Lesenswert?

Danke nochmals für eure Untersützung.

Ich habe allerdings noch ein Problem mit einer Konvertierung: Ich möchte das Datum in einen string umwandeln für die weitere Verarbeitung. Dazu nutze ich die Funktion strftime:

Datum Zeit:

1
sec = 30
2
min = 59
3
hour = 9
4
month_day = 27
5
month = 3
6
year = 123
7
day_of_week = 4
8
day_of_year 117
9
time_zone = 100663296

Nun soll mit Hilfe der Funktion strftime diese obigen Werete in ein string umgewandlet werden:

1
char buffer[10];
2
strftime (buffer, 10, "%Y:%m:%d", &DateTime);

Im Buffer steht dann folgendes:

1
buffer[0]  char  50 '2'  0x20000780  
2
buffer[1]  char  48 '0'  0x20000781  
3
buffer[2]  char  50 '2'  0x20000782  
4
buffer[3]  char  51 '3'  0x20000783  
5
buffer[4]  char  58 ':'  0x20000784  
6
buffer[5]  char  48 '0'  0x20000785  
7
buffer[6]  char  52 '4'  0x20000786  
8
buffer[7]  char  58 ':'  0x20000787  
9
buffer[8]  char  50 '2'  0x20000788  
10
buffer[9]  char  55 '7'  0x20000789

Das stimmt aber nicht. Der zweite Wert sollte nicht 4 sein sondern 3.

#7380928
Lesenswert?

He S. schrieb:

Das stimmt aber nicht. Der zweite Wert sollte nicht 4 sein sondern 3.

Nochmal:

Εrnst B. schrieb:

1
 struct tm {
2
            int         tm_sec;    /* Seconds          [0, 60] */
3
            int         tm_min;    /* Minutes          [0, 59] */
4
            int         tm_hour;   /* Hour             [0, 23] */
5
            int         tm_mday;   /* Day of the month [1, 31] */
6
            int         tm_mon;    /* Month            [0, 11]  (January  = 0) */
7
            int         tm_year;   /* Year minus 1900 */
8
            int         tm_wday;   /* Day of the week  [0, 6]   (Sunday =  0) */
9
            int         tm_yday;   /* Day of the year  [0, 365] (Jan/01 =  0) */
10
            int         tm_isdst;  /* Daylight savings flag */
11
            long        tm_gmtoff; /* Seconds East of UTC */
12
            const char *tm_zone;   /* Timezone abbreviation */
13
        };

Überleg dir, was der Kommentar "January = 0" für die Monate Februar, März, April... aussagt.

#7380991
Lesenswert?

Ich habe mal die Gauss'sche Osterformel benutzt. Ein altes Foto vom Ostersonntag, ohne Jahresangabe. Ein kleines Basic-Programm lieferte mir die Hauptverdächtigen (Aus der Mode der abgebildeten Kleidung ließ es sich etwa abschätzen). https://de.wikipedia.org/wiki/Gau%C3%9Fsche_Osterformel da spielt noch der Vollmondtermin eine Rolle, das macht es etwas komplizierter.

#7381016
Lesenswert?

void rtc_update_dofw_and_week(TimeDate *ptr) { if (ptr != NULL) { unsigned int x_year = 1900; unsigned int y_month = 1;

1
if (ptr->year >= 2000) {
2
  ptr->dofw_calendar = 5;//first day of year 2000 Szombat
3
  for (x_year = 2000; x_year < ptr->year; x_year++) {
4
    for (y_month = 1; y_month <= 12; y_month ++) {
5
      ptr->dofw_calendar += rtc_get_day_in_month(x_year, y_month);
6
      ptr->dofw_calendar %= 7;
7
    }
8
  }
9
}
10
{
11
  unsigned char i = 0;
12
  ptr->week_calendar = 0;
13
  if (ptr->dofw_calendar < 3) {
14
    ptr->week_calendar ++;
15
  }
16

17
  for (i = 1; i < ptr->month; i++) {
18
    ptr->dofw_calendar += rtc_get_day_in_month(ptr->year, i) % 7;
19
    ptr->week_calendar += rtc_get_day_in_month(ptr->year, i) / 7;
20
  }
21
  ptr->dofw_calendar += (ptr->day - 1) % 7;
22
  ptr->week_calendar += (ptr->day - 1) / 7;
23
  ptr->week_calendar += ptr->dofw_calendar / 7;
24
  ptr->dofw_calendar = ptr->dofw_calendar % 7;
25
}

} }

unsigned char rtc_is_leap_year(unsigned int year) { unsigned char result = 0; if ((year % 400) == 0) { result = 1; } else { if ((year % 100) == 0) { result = 0; } else { if ((year % 4) == 0) { result = 1; } else { result = 0; } } } return result; }

unsigned char rtc_get_day_in_month(unsigned int year, unsigned int month) { unsigned char result = 1; if ((month >= MONTH_MIN) && (month <= MONTH_MAX)) { if ((month == 2) && (rtc_is_leap_year(year) == 1)) { result = day_in_month[MONTH_LEAP]; } else { result = day_in_month[month]; } } return result; }

#7383317
Lesenswert?

Εrnst B. schrieb:

He S. schrieb:

Das stimmt aber nicht. Der zweite Wert sollte nicht 4 sein sondern 3.

Nochmal:

Εrnst B. schrieb: struct tm { int tm_sec; /* Seconds [0, 60] / int tm_min; / Minutes [0, 59] / int tm_hour; / Hour [0, 23] / int tm_mday; / Day of the month [1, 31] */ .... };

Kann nicht mal wer diese Info in ein Youtube-Video packen? Entsprechend dem Niveau der "Programmierer" hier - denn schnödes Lesen ist ja so was von altbacken ...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren