Author Topic: Calculate week number  (Read 4981 times)

jalih

• Posts: 91
Calculate week number
« on: November 06, 2018, 10:03:36 am »
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: [Select]
`*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;`

John

• Forum Support / SB Dev
• Posts: 3116
Re: Calculate week number
« Reply #1 on: November 06, 2018, 11:27:09 am »
Perl

Code: Perl
1. use DateTime;
2.
3. print DateTime->now->week_number,"\n";
4.

\$ perl weeknow.pl
45
\$

jalih

• Posts: 91
Re: Calculate week number
« Reply #2 on: November 06, 2018, 11:54:27 am »
Perl
Code: Perl
1. use DateTime;
2.
3. print DateTime->now->week_number,"\n";
4.

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

John

• Forum Support / SB Dev
• Posts: 3116
Re: Calculate week number
« Reply #3 on: November 06, 2018, 03:12:11 pm »
PHP

Code: PHP
1. <?php
2. echo date('W')."\n";
3. ?>
4.

\$ php weeknow.php
45
\$

John

• Forum Support / SB Dev
• Posts: 3116
Re: Calculate week number
« Reply #4 on: November 06, 2018, 03:41:47 pm »
Python

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

\$ python weeknow.py
45
\$

AIR

• BASIC Developer
• Posts: 817
Re: Calculate week number
« Reply #5 on: November 06, 2018, 07:12:41 pm »
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.

Sometimes the most obvious solution is one that isn't considered:

Code: Bash
1. /bin/date -d "20100215" +%V

Returns Week #7 of 2010.

AIR.

AIR

• BASIC Developer
• Posts: 817
Re: Calculate week number
« Reply #6 on: November 06, 2018, 08:55:27 pm »
Okay, all kidding aside, here's a function written in BaCon (compile with: bacon -y -o -D_GNU_SOURCE weekofdate.bac):

Code: Text
1. PRAGMA INCLUDE <time.h>
2.
3. DECLARE tmm TYPE struct tm
4.
5. PROTO strptime
6. PROTO strftime
7.
8.
9. FUNCTION getWeekNumber\$(int yr, int mon, int day) TYPE STRING
10.     LOCAL format\$
11.     PRINT yr,mon,day FORMAT "%d-%02d-%02d" TO format\$
12.     strptime(format\$, "%Y-%m-%d", &tmm)
13.     strftime(format\$, SIZEOF(format\$), "%V", &tmm)
14.     RETURN format\$
15. END FUNCTION
16.
17.
18. PRINT "WEEK Number is: ", getWeekNumber\$(2010,02,15)
19.

AIR.

John

• Forum Support / SB Dev
• Posts: 3116
Re: Calculate week number
« Reply #7 on: November 06, 2018, 09:09:55 pm »
I swear SB had a WEEKNUMBER() or FORMATDATE() option to return the week number. No joy.

AIR

• BASIC Developer
• Posts: 817
Re: Calculate week number
« Reply #8 on: November 06, 2018, 09:40:56 pm »
You're getting old, John.  You have FORMATDATE and TIMEVALUE.  LOL.

Look in examples/testtime.bas.

Geez, I don't even use SB that much and I know this!!!

AIR.

AIR

• BASIC Developer
• Posts: 817
Re: Calculate week number
« Reply #9 on: November 06, 2018, 10:28:39 pm »
This is one of those things you could stick in a utility module.  I called it "timeutils".

Code: Script BASIC
1. import timeutils.bas
2.
3. print timeutils::WeekNumber(2015,02,15)
4.

riveraa@nas:~/src/sb_ubuntu-64\$ ./AppRun testweek.bas
07

Interface:

Code: Script BASIC
1. /*
2. READ THIS FILE AND CHANGE THE SOURCE WHEREVER YOU SEE COMMENTS STARTING
3. WITH THE WORD *TODO*
4.
5. WHEN YOU ARE FINISHED YOU CAN
6.
7.   FILE   : interface.c
8.   HEADER : interface.h
9.   BAS    : timeutils.bas
10.   AUTHOR : AIR
11.
12.   DATE:
13.
14.   CONTENT:
15.   This is the interface.c file for the ScriptBasic module timeutils
16. ----------------------------------------------------------------------------
17.
18.
19.
20. UXLIBS:-lm -ldl
21. ----------------------------------------------------------------------------
22.
23. DWLIBS:
24.
25. */
26.
27.
28.
29. #include <stdio.h>
30. #include <stdlib.h>
31. #include <string.h>
32. #include <time.h>
33. #include "../../basext.h"
34.
35.
36. typedef struct _ModuleObject {
37.   char a; /* You may delete this. It is here to make the initial interface.c compilable. */
38.   }ModuleObject,*pModuleObject;
39.
40.
41.
42. besVERSION_NEGOTIATE
43.   return (int)INTERFACE_VERSION;
44. besEND
45.
46.
47. besSUB_ERRMSG
48.
49.   switch( iError ){
50.     case 0x00080000: return "ERROR HAS HAPPENED";
51.     }
52.   return "Unknown timeutils module error.";
53. besEND
54.
55.
56. besSUB_START
57.   pModuleObject p;
58.
59.   besMODULEPOINTER = besALLOC(sizeof(ModuleObject));
60.   if( besMODULEPOINTER == NULL )return 0;
61.
62. besEND
63.
64.
65. besSUB_FINISH
66.   pModuleObject p;
67.
68.   /*
69.     YOU CERTAINLY NEED THIS POINTER TO FREE ALL RESOURCES THAT YOU ALLOCATED
70.     YOU NEED NOT CALL besFREE TO FREE THE MEMORY ALLOCATED USING besALLOC
71.     CLOSE ANY FILE THAT REMAINED OPEN, RELEASE DATABASE HANDLES AND ALL
72.     OTHER RESOURCES INCLUDING MEMORY *NOT* ALLOCATED CALLING besALLOC
73.   */
74.   p = (pModuleObject)besMODULEPOINTER;
75.   if( p == NULL )return 0;
76.
77.   return 0;
78. besEND
79.
80.
81. /**
82. =section WeekNumber
83. =H title that goes into the BASIC documentation for this function
84.
85. detail here what the function does so that the BASIC programmer
86. can understand how he/she can use it
87. */
88. besFUNCTION(WeekNumber)
89.   pModuleObject p;
90.   struct tm tm;
91.   char format[32];
92.   int yr,mon,day;
93.
94.   p = (pModuleObject)besMODULEPOINTER;
95.
96.   besARGUMENTS("iii")
97.   &yr,&mon,&day
98.   besARGEND
99.
100.   sprintf(format,"%d-%02d-%02d",yr,mon,day);
101.   strptime(format, "%Y-%m-%d", &tm);
102.   strftime(format, sizeof(format),"%V", &tm);
103.   besSET_RETURN_STRING(format);
104. besEND
105.
106.
107. SLFST TIMEUTILS_SLFST[] ={
108.
109. { "versmodu" , versmodu },
110. { "bootmodu" , bootmodu },
111. { "finimodu" , finimodu },
112. { "emsgmodu" , emsgmodu },
113. { "WeekNumber" , WeekNumber },
114. { NULL , NULL }
115.   };
116.

AIR.

John

• Forum Support / SB Dev
• Posts: 3116
Re: Calculate week number
« Reply #10 on: November 06, 2018, 10:49:45 pm »
You are the master extension builder! SQLite, MiniXML, ...

THANKS!

Quote
You're getting old, John.  You have FORMATDATE and TIMEVALUE.  LOL.

Neither helps to return a week number.

FWIW

I tried to use the SQLite DateTime() function to return to week number (%W) but it didn't seem to work.

« Last Edit: November 07, 2018, 01:39:52 am by John »

AIR

• BASIC Developer
• Posts: 817
Re: Calculate week number
« Reply #11 on: November 07, 2018, 06:28:06 am »
One way of doing it:

Code: Script BASIC
1. INCLUDE sqlite.bas
2.
3. hdb=sqlite::open("testsql")
4. sqlite::execute(hdb,"create table demo (week text);")
5. sqlite::execute(hdb, "INSERT INTO demo VALUES (strftime('%W','now'));")
6. stmt = sqlite::query(hdb,"SELECT week FROM demo;")
7. while (sqlite::row(stmt) = 100)
8.         print sqlite::row_value(stmt,0),"\n"
9. wend
10.
11. sqlite::close(hdb)

AIR.

John

• Forum Support / SB Dev
• Posts: 3116
Re: Calculate week number
« Reply #12 on: November 07, 2018, 08:14:34 am »
Cool!

I was a little Lite with my SQL code.

I'm officially adding your WEEKNUMBER() function to the T (Tools) extension module today.
« Last Edit: November 07, 2018, 08:58:34 am by John »

AIR

• BASIC Developer
• Posts: 817
Re: Calculate week number
« Reply #13 on: November 07, 2018, 09:40:44 am »
Or........

Code: Script BASIC
1. print formatdate("Today is WDN MON DD, YEAR"),"\n"
2.
3. print formatdate("The current week number of the year is: WEEKNUM"),"\n"

AIR.

Edit:  Set img to a more reasonable size!! LOL
« Last Edit: November 07, 2018, 09:44:19 am by AIR »

AIR

• BASIC Developer
• Posts: 817
Re: Calculate week number
« Reply #14 on: November 07, 2018, 09:55:15 am »
I'm officially adding your WEEKNUMBER() function to the T (Tools) extension module today.

Note that it makes use of a function that is not available in VC on Windows, but IS available in MinGW.