BASIC User Group > Code Challenges

Calculate week number

(1/4) > >>

jalih:
Your challenge is to write a procedure that returns the week number for a given date. If week number belongs to a week numbering of the previous year then that week number should be returned instead of the zero week.

Here is my PL/I version using bit strings to turn calculations into simple string search:

--- Code: ---
*PROCESS MARGINS(1, 140);

 test: proc options (main);
   dcl 1 date_type based,
         2 day   pic'99',
         2 month pic'99',
         2 year  pic'9999';

   dcl d like date_type;

   /* fill date structure */
   d.day   = '06';
   d.month = '11';
   d.year =  '2018';

   /* test our proggy */
   put skip list (trim(week(d)));

 /****************************************************************************************************************/
   week: proc (day) returns (fixed bin (31));
     dcl day like date_type;

     dcl (from, to) like date_type;
     dcl (days_from, days_to) fixed bin (31);
     dcl total_days fixed bin (31);
     dcl week_index fixed bin (31);
     dcl weeknro fixed bin (31);
     dcl result bit (*) aligned controlled;
     dcl weeks (7) bit (7) aligned nonasgn
         init ('0100000'b, '0010000'b, '0001000'b, '0000100'b, '0000100'b, '0000010'b, '0000001'b);
     dcl masks (7) bit (7) aligned nonasgn
         init ('0111100'b, '1111000'b, '1110001'b, '1100011'b, '1000111'b, '0001111'b, '0011110'b);
     dcl bool bit (1);

     dcl (days, weekday, tally, substr, lbound, hbound, copy, omitted) builtin;

     /* we start from first of january, naturally */
     from.day   = '01';
     from.month = '01';
     from.year  = day.year;

     to = day;

     days_from = days(string(from), 'DDMMYYYY');
     days_to   = days(string(to), 'DDMMYYYY');

     /* calculate required length for the bit string */
     total_days = days_to - days_from + 1;

     /* allocate bit string, holding date range */
     allocate result bit (total_days);

     /* fill bit string with correct rotation of the week pattern */
     week_index = weekday(days_from);
     result = copy(weeks(week_index), total_days / 7) || substr(weeks(week_index), 1, mod(total_days, 7));

     /* find the number of weeks starting on monday */
     weeknro = tally(result, '1'b);

     /* free allocated storage */
     free result;

     /* first week can be partial and if it includes thursday, then add it to the result */
     bool = substr(masks(week_index), 1, 1);
     if bool then weeknro += 1;

     /* maybe first days of the year belong to week numbering of the previous year? */
     if weeknro = 0 then
       do;
         from.year -= 1;
         to = from;
         to.day   = '31';
         to.month = '12';

         days_from = days(string(from), 'DDMMYYYY');
         days_to   = days(string(to), 'DDMMYYYY');

         total_days = days_to - days_from + 1;
         allocate result bit (total_days);

         week_index = weekday(days_from);

         result = copy(weeks(week_index), total_days / 7) || substr(weeks(week_index), 1, mod(total_days, 7));
         weeknro = tally(result, '1'b);
         free result;
       end;
     return (weeknro);
   end week;
 /****************************************************************************************************************/
 end test;

--- End code ---

John:
Perl


--- Code: Perl ---use DateTime; print DateTime->now->week_number,"\n"; 

$ perl weeknow.pl
45
$

jalih:

--- Quote from: John on November 06, 2018, 11:27:09 am ---Perl

--- Code: Perl ---use DateTime; print DateTime->now->week_number,"\n"; 
--- End quote ---

Okay, that is certainly shorter than my PL/I version.  ???

John:
PHP


--- Code: PHP ---<?phpecho date('W')."\n";?> 

$ php weeknow.php
45
$



John:
Python


--- Code: Python ---from datetime import date print date.today().isocalendar()[1] 

$ python weeknow.py
45
$


Navigation

[0] Message Index

[#] Next page

Go to full version