Posts: 1,956
Threads: 65
Joined: Jun 2003
Xhantt, you didn't answer my questions. I already understand about Gregorian and Julian dates.
I could not access the site you gave me yesterday, and I still can't today.
*****
Posts: 90
Threads: 8
Joined: Aug 2003
Let me trya again
The parameters are year, month, day, ut (universal time zone my is GMT-3 so is -3, in GMT is 0 ).
When i put fix(a) i mean it to be the greatest integer less than a. Ej. 1.34 -> 1, -2.3 -> -3, 1.75 -> 1, -2.7 -> -3.
I tune my programin knowing that may 25th of 1810 was friday. Then i try current date and my birthday date.
Code: a# = JulianDate#(2004, 6, 11, 0) '-> current date is friday
b# = JulianDate#(1900, 1, 1, 0) '-> date to test
d& = FIX(a# - b#) ' -> days elapsed
PRINT "January 1th, 1900 was ";
SELECT CASE d& MOD 7 ' -> we get day of the week
CASE 0: PRINT "friday" '-> same day of the week
CASE 1: PRINT "thursday" '-> b is the day after so b is thursday
CASE 2: PRINT "wednesday" '-> and so on
CASE 3: PRINT "tuesday"
CASE 4: PRINT "monday"
CASE 5: PRINT "sunday"
CASE 6: PRINT "saturday"
END SELECT
Google "julian date" and pick up Eric Weisstein's world of astronomy. I dont know why the link doesnt work i copy from the address bar :???:.
I think it should work.
Posts: 2,771
Threads: 96
Joined: Oct 2003
Xhantt: The link does work. just so ya know.
Posts: 1,956
Threads: 65
Joined: Jun 2003
Xhantt,
I did some testing with your original version of Wednesday June 9.
I almost works. The number of Tuesdays or Thurdays is one less than the correct number. For example, if you put in a date of Monday June 7, you get a count of zero.
Maybe the FIX(dias/7) is not working just right.
Anyway, you get an "A" for effort, and so far you're the only winner.
*****
Posts: 90
Threads: 8
Joined: Aug 2003
Thanks, i'm glad to help you.
Posts: 1,956
Threads: 65
Joined: Jun 2003
Xhantt,
I looked up the FIX command. For positive numbers it's the same as using an INT. For negative numbers it truncates the decimals, whereas INT will truncate but increment the whole number part by one.
However, your code still has a problem. Your statement:
PRINT "Han pasado "; FIX(dias / 7); " jueves"
will print the truncated number of weeks between the two dates. The number of weeks is not necessarily the number of Tuesdays or Thurdays that transpired, because the first date could have started on a Tuesday and the end date could end on a Wednesday which means that you have 2 extra Tuesdays in the count.
You need to add a little routine that computes the day of the week for a given value which you call JulianDate#.
I suggest you do some more testing with real, small dates that can be checked manually with a calendar.
*****
Posts: 1,956
Threads: 65
Joined: Jun 2003
Ok guys, here's my solution. I used a bunch of date handling routines that I already had. The actual Tuesday logic is a small FOR loop that's very simple. A more clever algorithm might be used, but why spend the energy.
You run the program with a command-line parameter of the "from" date you want in the format YYYYMMDD.
Try it out.
*****
Code: REM *** Program to count number of Tuesdays from input date to today-1.***
DEFINT A-Z
DECLARE FUNCTION IsLeapYear% (Z)
DIM YEAR.MIN AS INTEGER 'Minimum valid year for dates (default=0)
DIM DATE.FACTOR AS SINGLE 'Number of days given date is from day zero.
DIM WEEK.DAY AS INTEGER 'Day of week value: 1=Sunday....7=Saturday.
DIM WEEK.NUM AS INTEGER 'Week number within year (1 to 54).
DIM JULIAN.DAY AS INTEGER 'Day number within year (1 to 366).
DIM DATE.OK AS INTEGER 'Valid date indicator: -1=True, 0=False.
Z$ = "" 'Date string as YYYYMMDD.
DIM ZYY AS INTEGER 'Value of the 4 digit year.
DIM ZMM AS INTEGER 'Value of the 2 digit month.
DIM ZDD AS INTEGER 'Value of the 2 digit day.
DIM ZDWORK AS LONG 'Variable internal to date routines.
DIM ZFSAVE AS SINGLE 'Variable internal to date routines.
DIM ZFSAVE2 AS SINGLE 'Variable internal to date routines.
ZTEMP$ = "" 'Work string internal to date routines.
'NOTE: The following variable ZMO() is internal to date routines.
DIM ZMO(1 TO 12) AS INTEGER
DATA 31,28,31,30,31,30,31,31,30,31,30,31
FOR ZMM=1 TO 12:READ ZMO(ZMM):NEXT
dim factor1 as single
dim factor2 as single
dim dtfact as single
dim tcount as long
REM *** MAIN LINE *************************************************************
param1$ = ltrim$(rtrim$(command$)) 'input date (from)
gosub date.today:param2$=z$
print param1$
print param2$
z$=Param1$
gosub date.factor
factor1=date.factor
if not(date.ok) then print "Invalid input date, must be YYYYMMDD":system
if param1$ >= param2$ then print "Input date >= today, nothing to do":system
z$=Param2$
gosub date.factor
factor2=date.factor
for dtfact=factor1 to factor2-1
date.factor=dtfact
gosub compute.weekday
if week.day=3 then tcount=tcount+1 'count Tuesdays (3)
next dtfact
print:print "Number of Tuesdays between ";param1$;" and today is ";tcount
SYSTEM
REM ************************ DATE.FACTOR ************************************
REM *
REM *** PRINCIPAL DATE SUBROUTINE:
REM * =========================
REM * - Validate input date string.
REM * - Compute number of days (date.factor) from year 0, month 0, day 0.
REM * - Compute day of week.
REM * - Compute week number.
REM * - Compute "julian" day of year.
REM *
REM * INPUT:
REM * =====
REM * Z$ = Date string formatted as YYYYMMDD.
REM * YEAR.MIN = Minimum year user wishes to allow (default 0)
REM *
REM * OUTPUT:
REM * ======
REM * DATE.OK = -1 if input date VALID. (true)
REM * = 0 if Input date INVALID. (false)
REM * NOTE: IF VALID, THE FOLLOWING VARIABLES AR BASED ON INPUT DATE.
REM * IF INVALID, THE VALUES MAY HAVE CHANGED AND ARE MEANINGLESS.
REM * DATE.FACTOR = Number of cumulative days from year/month/day 0.
REM * WEEK.DAY = 1 to 7 is Sunday to Saturday respectively.
REM * WEEK.NUM = 1 TO 54 is week number within year.
REM * JULIAN.DAY = 1 TO 366 is day number within year.
REM * ZYY = Value of of 4 digit year.
REM * ZMM = Value of month.
REM * ZDD = Value of day.
REM * EASTERSUNDAY$ = Date of Easter for given year.
REM * Z$ = (unchanged).
REM * YEAR.MIN = (unchanged).
REM *
REM *
REM * Date factor logic adopted from a Texas Instruments calculator manual.
REM *
DATE.FACTOR:
gosub Date.Check 'check input date
if not(date.ok) then RETURN 'exit if invalid
zmm=1:zdd=1 'set to January 1st
gosub Compute.Factor 'compute factor of Jan 1st
zfsave=date.factor 'save factor of Jan 1st
gosub Compute.Weekday 'week.day now has day of week of Jan 1st
zdd=val(right$(z$,2)) 'Restore input date's day + month
zmm=val(mid$(z$,5,2))
gosub Compute.Factor 'compute factor of input date
'* Julian day is input date minus Jan 1st of same year +1
julian.day=date.factor-zfsave+1
'* Compute the week number: (week.day-1 is week day of Jan 1st relative to 0)
week.num=int((julian.day+(week.day-1)-1)/7)+1
'* Compute the day of the week of input date:
gosub Compute.Weekday
RETURN
COMPUTE.FACTOR:
DATE.FACTOR=365!*ZYY+ZDD+31*(ZMM-1) 'NOTE: WON'T WORK WITHOUT ! AFTER 365.
IF ZMM<3 THEN
DATE.FACTOR=DATE.FACTOR+INT((ZYY-1)/4)-INT(3/4*(INT((ZYY-1)/100)+1))
ELSE
DATE.FACTOR=DATE.FACTOR-INT(.4*ZMM+2.3)+INT(ZYY/4)-INT(3/4*(INT(ZYY/100)+1))
END IF
RETURN
COMPUTE.WEEKDAY:
'* Compute the day of the week:
WEEK.DAY=DATE.FACTOR-INT(DATE.FACTOR/7)*7 'Modulo 7.
IF WEEK.DAY=0 THEN WEEK.DAY=7 'WEEK.DAY=1=Sunday.
RETURN
REM ****************** DATE.TODAY *******************************************
REM *
REM *** SUBROUTINE TO GET TODAY'S DATE AND FORMAT AS YYYYMMDD.
REM *
REM * INPUT: (None)
REM *
REM * OUTPUT: Z$ = Today's date, string as YYYYMMDD.
REM *
DATE.TODAY:
z$=date$ 'Date is mm-dd-yyyy
if left$(time$,2)="00" then z$=date$ 'make sure date didn't just roll over
Z$=right$(z$,4)+left$(z$,2)+mid$(z$,4,2) 'in YYYYMMDD format
RETURN
REM ********************* DATE.CHECK ****************************************
REM *
REM *** VALIDATE A DATE IN YYYYMMDD FORMAT.
REM *
REM * INPUT: Z$ = Given date in format YYYYMMDD.
REM * YEAR.MIN = Minimum valid year allowed. (default=0)
REM *
REM * OUTPUT: DATE.OK = -1 if input date is VALID. (true)
REM * 0 if input date is INVALID. (false)
REM * (if VALID):
REM * ZYY = Value of 4 digit year.
REM * ZMM = Value of month.
REM * ZDD = Value of day.
REM *
REM *
DATE.CHECK:
DATE.OK = 0 'preset to false
ZTEMP$="1"+Z$+"1"
IF LEN(Z$)<>8 OR MID$(STR$(VAL(ZTEMP$)),2)<>ZTEMP$ THEN RETURN
ZDD=VAL(RIGHT$(Z$,2)) 'Set day
ZMM=VAL(MID$(Z$,5,2)) 'Set month.
ZYY=VAL(LEFT$(Z$,4)) 'Set year.
IF ZMM<1 OR ZMM>12 OR ZDD<1 OR ZDD>31 OR ZYY<YEAR.MIN THEN RETURN
IF ZMO(ZMM)+1*(-(ZMM=2 AND ISLEAPYEAR(ZYY))) < ZDD THEN RETURN
' If expression (month=2 and is leapyear) is TRUE which is -1, then
' taking the negative of this issues a plus 1. Conversely, the FALSE
' always gives a zero. Multiplying the +1 by this result of 1 or 0
' will either add 1 or not to the number of days in the month.
' The routine wants to add 1 only when it is February and leap year.
DATE.OK = -1 '-1=valid (true)
RETURN
REM ***************************************************************************
END
' ====================== ISLEAPYEAR ==========================
' Determines if a year is a leap year or not.
' ============================================================
'
FUNCTION IsLeapYear (Z) STATIC
' If the year is evenly divisible by 4 and not divisible
' by 100, or if the year is evenly divisible by 400, then
' it's a leap year:
IsLeapYear = (Z MOD 4 = 0 AND Z MOD 100 <> 0) OR (Z MOD 400 = 0)
END FUNCTION
Posts: 90
Threads: 8
Joined: Aug 2003
Last code. I fix the 'fix' problem and count the last tuesday :-)
Code: FUNCTION JulianDate# (y%, m%, d%, ut%)
DIM a, b, c
a = INT(7# * (y% + INT((m% + 9#) / 12#)) / 4#)
b = INT(3# * (INT((y% + (m% - 9#) / 7#) / 100#) + 1#) / 4#)
c = INT(275 * m% / 9#) + d% + 1721028.5# + ut% / 24#
JulianDate# = 367# * y% - a - b + c
END FUNCTION
'Tuesdays elapsed between y1-m1-d1 and y2-m2-d2, including y1-m1-d1
' but not including y2-m2-d2
FUNCTION TuesdaysElapsed# (y1%, m1%, d1%, y2%, m2%, d2%)
DIM j1, j2, j3 AS DOUBLE
DIM WE AS DOUBLE
DIM TE AS DOUBLE
j1 = JulianDate#(y1%, m1%, d1%, 0)
j2 = JulianDate#(y2%, m2%, d2%, 0)
'Weeks elapsed
WE = INT((j2 - j1) / 7)
'for each complete week there's one tuesday
TE = WE
'next tuesday not counted
j3 = j1 + WE * 7 + (7 - (INT(j1) MOD 7)) MOD 7
'if next tuesdays is before y2-m2-d2 count it
IF j3 < j2 THEN TE = TE + 1
TuesdaysElapsed# = TE
END FUNCTION
Posts: 1,956
Threads: 65
Joined: Jun 2003
Xhantt,
Looks much better. Give me a few days to test it out.
*****
Posts: 1,956
Threads: 65
Joined: Jun 2003
Xhantt,
I inserted your functions into a test program and they run fine. I ran some parallel tests with my solution and the results were the same.
So, congratulations, you are the winner!
*****
|