Home > Software design >  Get week number of month from timestamp in micros without using libraries
Get week number of month from timestamp in micros without using libraries

Time:08-09

I need a function that will give the week number of the month from micros without using libraries. Signature of function to better understand what I mean: getWeekOfMonth(long timestamp, int m, isLeapYear(y)).

I searched the Internet to find some information, but there is only information about how to write with libraries.

CodePudding user response:

First you need to define timestamp correctly. You need a starting date/time where your time is equal to zero. This is usually called epoch (in astronomy).

From this there are 2 approaches to get the year,month,week,dayofweek. Either you handle any time change relatively to lastly computed date/time or you compute the stuff using modular arithmetics and rules...

I prefer the first one as I often deal with astronomy times where there are many irregular corrections of time that would be too complicated to code with the second approach but its slower.

The basic rules are:

  1. leap year is every 4 years but not every 100 except every 400 years

  2. february has 1 day more in leap year

so naive version of 2nd approach can look like this in C on integers (if t is number in days from 1.1.0000 00:00:00):

const int months[2][12]= {{ 31,28,31,30,31,30,31,31,30,31,30,31 },  // normal
                         { 31,29,31,30,31,30,31,31,30,31,30,31 }}; // leap
year = t/(4*365 1); t -=  year*(4*365 1);
year  = t/365;      t -=  365*(t/365);
leap = ((year % 4 == 0) AND (year % 100 != 0)) OR (year % 400 == 0)
for (month=0;month<12;) 
 if (t>months[leap][month]){ t-=months[leap][month]; month  ; }
  else break;

now day of week and week of month can be done in similar fashion (note I did not test code above I just wrote it directly in here). Also beware I count months from 0 so if you want to print them just use increment.

The 1st approach I am usually doing like this (tested and heavily used ancient C code hope I did not forget to copy something):

//---------------------------------------------------------------------------
const double t_rok=365.242195601852;    // tropick year in days
const double t_den=  1.0;               // mean stellar day
const double t_hod=t_den/24.0;
const double t_min=t_hod/60.0;
const double t_sec=t_min/60.0;

const double time_t0  =0.0;  // epoch
const int    time_den7=5;    // sobota (saturday)
const int    time_den0=0;
const int    time_mes0=0;
const int    time_rok0=2000;

const int    time_kalen[2][12]= {{ 31,28,31,30,31,30,31,31,30,31,30,31 },   // normal
                                 { 31,29,31,30,31,30,31,31,30,31,30,31 }}; // priestupny
const AnsiString time_week[7]= { "Pondelok","Utorok","Streda","Stvrtok","Piatok","Sobota","Nedela" };

//---------------------------------------------------------------------------
class   time_
    {
public:
    int     den,mes,rok,den7;    // day ,month, year,
    int     hod,min,sec;
    double  _tr0,_tr1;          // t on start if this and next year
    double  t,ut,dut,JD,jd;     // t is SEC 1 hod, ut is universal time,dut is shift -1*t_hod or -2 hod*t_hod (summer/winter), JD is julian date, jd is "jullian" after year 2000
    time_() {den7=time_den7;t=time_t0;den=time_den0;mes=time_mes0;rok=time_rok0;hod=0;min=0;sec=0;_tr0=0;_tr1=365;if(priestupny(rok))_tr1  ;setut();}
    time_(time_& a){ *this=a; }; ~time_(){}; time_* operator = (const time_ *a) { *this=*a; return this; }; /*time_* operator = (const time_ &a) { ...copy... return this; };*/
    int  priestupny(int rok); // leap year?
    void date(int,int,int,int,int,int);
    void time(double);          // this sets time absolutely
    void add_time(double);      // this adds to actual time relatively
    void setut();               // this updates ut
    void inc_rok();             // helper function for year change
    void dec_rok();             // helper function for year change
    void set_actual_time();     // this loads actual system time
    AnsiString str0();          // string output: d.m.yyyy hh:mm:ss day
    AnsiString str1();          // string output: UT = hh:mm:ss
    };
//---------------------------------------------------------------------------
int time_::priestupny(int r)
    {
    int     p=0;                  // priestupny rok ?
    if (r%  4==0) p=1;
    if (r0==0) p=0;
    if (r@0==0) p=1;
    return p;
    }
//---------------------------------------------------------------------------
void time_::inc_rok()
    {
    rok  ;
    _tr0=_tr1;
    _tr1 =365;
    if (priestupny(rok)) _tr1  ;
    }
//---------------------------------------------------------------------------
void time_::dec_rok()
    {
    rok--;
    _tr1=_tr0;
    _tr0-=365;
    if (priestupny(rok)) _tr0--;
    }
//---------------------------------------------------------------------------
void time_::date(int d,int m,int r,int hh,int mm,int ss)
    {
    if ((m<1)||(m>12)||(d<1)||(d>31)) return;   // prevent freeze on invalid date
    int     ki,pr;
    d--;
    m--;
    t=floor(t);
    pr=priestupny(rok);
    ki= 1;
    if (d>den) ki= 1; if (d<den) ki=-1;
    if (m>mes) ki= 1; if (m<mes) ki=-1;
    if (r>rok) ki= 1; if (r<rok) ki=-1;
    while((r!=rok)||(m!=mes)||(d!=den))
            {
            t =ki;
            den =ki;
            if ((ki>0)&&(den>=time_kalen[pr][mes]))
                    {
                    mes  ;
                    if (mes>=12)
                            {
                            mes=0;
                            inc_rok();
                            pr=priestupny(rok);
                            }
                    den=0;
                    }
            if ((ki<0)&&(den<0))
                    {
                    mes--;
                    if (mes<0){
                            mes=11;
                            dec_rok();
                            pr=priestupny(rok);
                            }
                    den=time_kalen[pr][mes]-1;
                    }
            }
    hod=hh;
    min=mm;
    sec=ss;
    t =hod/24.0;
    t =min/1440.0;
    t =sec/86400.0;
    setut();
    }
//---------------------------------------------------------------------------
void time_::time(double dt)
    {
    add_time(dt-t);
    }
//---------------------------------------------------------------------------
void time_::add_time(double dt)
    {
    double  q;
    int     pr;
    t =dt;
    q=t-_tr0;
    while (q<0)
            {
            dec_rok();
            q =(_tr1-_tr0);
            }
    while (q _tr0>=_tr1)
            {
            q-=(_tr1-_tr0);
            inc_rok();
            }
    pr=priestupny(rok);
    den=floor(q);
    mes=0;
    while(den>=time_kalen[pr][mes])
            {
            den-=time_kalen[pr][mes];
            mes  ;
            if (mes>=12) { mes=0; den=0; rok=0; }   // if error
            }
    q=t-floor(t);
    if (q<0) q  ;
    q*=24.0;  hod=floor(q);   q-=hod;
    q*=60.0;  min=floor(q);   q-=min;
    q*=60.0;  sec=floor(q);
    setut();
    }
//---------------------------------------------------------------------------
void time_::set_actual_time()
    {
    struct date ddd;
    struct time ttt;
    getdate(&ddd);
    gettime(&ttt);
    date( ddd.da_day,ddd.da_mon,ddd.da_year,ttt.ti_hour, ttt.ti_min, ttt.ti_sec);
    }
//---------------------------------------------------------------------------
AnsiString time_::str0()
    {
    AnsiString s;
    s="";
    s.sprintf("%.0i.%.0i.%.0i i:i:i ",den 1,mes 1,rok,hod,min,sec);
    return s time_week[den7];
    }
//---------------------------------------------------------------------------
AnsiString time_::str1()
    {
    AnsiString s;
    double  q;
    s="";
    q=hod floor(dut/t_hod);
    while (q>=24.0) q-=24.0;
    while (q<  0.0) q =24.0;
    s.sprintf("UT = %2.0f:%2i:%2i ",q,min,sec);
    return s;
    }
//---------------------------------------------------------------------------
void time_::setut()
    {
    den7=int(floor(t) time_den7)%7; if (den7<0) den7 =7;
    dut=-2.0*t_hod;
    if (mes>2) dut=-2.0*t_hod;
    if (mes>9) dut=-1.0*t_hod;
    ut=t dut;
    jd=ut 0.478;
    JD=jd 2451544.0;
//  posledna Nedela v marci   02:00 -> 03:00 ... dut=-2*t_hod
//  posledna Nedela v oktobti 03:00 -> 02:00 ... dut=-1*t_hod
    }
//---------------------------------------------------------------------------

Just translate the slavic names of days of week (Pondelok,Utorok...) also "Priestupny" means leap year. I am too lazy for that. The code expects time where integer part is day (from epoch) and fractional part hold time and it convert it to date and UT it time (winter/summer time shift included) and also Julian date JD as I use this for astronomy purposes

Now in order to add your week of month you need to process your month start day and count weeks from actual month. In the first approach just add something like this:

const int months[2][12]= {{ 31,28,31,30,31,30,31,31,30,31,30,31 },  // normal
                         { 31,29,31,30,31,30,31,31,30,31,30,31 }}; // leap
year = t/(4*365 1); t -=  year*(4*365 1);
year  = t/365;      t -=  365*(t/365);
leap = ((year % 4 == 0) AND (year % 100 != 0)) OR (year % 400 == 0)
for (month=0;month<12;) 
 if (t>months[leap][month]){ t-=months[leap][month]; month  ; }
  else break;
weekofmonth = t/7;

in the second approach you can do the same as t-_tr0 is time in days from start of this year so:

tt=t-_tr0;
for (month=0;month<12;) 
 if (tt>months[leap][month]){ tt-=months[leap][month]; month  ; }
  else break;
weekofmonth = tt/7;
  • Related