Im new to coding with REXX and I need to make a program to find the Max, min and avg temperature for every month.
The input is Comma separated like below:
DAY/MONTH,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
1st,25.9,25.4,31.3,22.4,8.1,7.3,12.9,13.1,11.3,15.2,19.2,21
2nd,27.2,22.3,18,14.6,10.2,10.9,10.9,13.5,15.9,24.9,26.2,17.2
3rd,34.9,16.6,19.1,20.8,10.6,10.7,7,11.1,14.5,25.1,28.9,22.9
4th,24.4,19.8,21.7,12.6,11.5,13,10.5,7.3,13.1,22.5,16.8,21.7
5th,14.1,21.8,18.9,14.4,15.4,11.7,10.5,8.4,14,11.4,13.8,23.4
... etc
I need to create REXX code to find the the Max, Min and Mean temperature for each month and present it like below
User,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
Max,34.9,16.6,19.1,20.8,10.6,10.7,7,11.1,14.5,25.1,28.9,22.9
Min,24.4,19.8,21.7,12.6,11.5,13,10.5,7.3,13.1,22.5,16.8,21.7
Mean,14.1,21.8,18.9,14.4,15.4,11.7,10.5,8.4,14,11.4,13.8,23.4
Any help in creating the REXX code, or any literature/direction on it would be greatly appreciated.
So far my code is
/*REXX*/
/* TRACE ?I */
ADDRESS SYSCALL "READFILE /u/inputdata RECS."
IF RC <> 0 THEN DO
SAY "ERROR READING FILE"
EXIT
END
FS=","; MAXTEMP=""; MINTEMP=""; AVGTEMP=""
DO I = 2 TO RECS.0
PARSE VAR RECS.I DAY","JAN","FEB","MAR","APR","JUN","JUL","AUG","SEP","OCT","NOV,"DEC
DO J = 2 TO RECS.I
MAXTEMP = MAX(RECS.I) /*Needs to add another VAR into Maxtemp*/
MINTEMP = MIN(RECS.I) /*same but Min */
AVGTEMP = SUM(RECS.I)/COUNT(RECS.I) /*Total/The amount of days*/
END
END
SAY user, JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
SAY MAX, MAXTEMP /*MAX for each month fill out*/
SAY MIN, MINTEMP /*Min */
SAY MEAN, AVGTEMP /*Avg */
END
Im trying to make a variable for MaxTemp, MinTemp and MeanTemp adding the months on as the loop goes.
Here is a possible implementation. It runs over each record as you did; this is the outer loop (loop variable ii). Then the current temperature for each month is
compared to the current maximum for that month, and stored if greater
compared to the current minimum for that month, and stored if lower
added to the average sum-up field for the month
This is the inner loop (lop variable jj). Note that the code inside this inner loop takes care not to process values for days beyond the maximum number of days per month.
Since the year for the data doesn't seem to be known, the correct number of days for February cannot be calculated. You would need to add that, if the year is known.
/*REXX*/
/* TRACE ?I */
address syscall "readfile /u/inputdata Recs."
if RC <> 0
then do
say "ERROR READING FILE"
exit 16
end
ifs = "," /* Field separator for parsing input records */
ofs = "," /* field separator for writing output records */
/* Initialize arrays to aggregate temperature data by month */
MaxTemp. = 0
MinTemp. = 99999
AvgTemp. = 0
/* Initialize array of number of days per month */
/* We do not know the year, so we cannot calculate whether February has 28 or 29 days */
DaysPerMonth.1 = 31
DaysPerMonth.2 = 28 /* Need to be adjusted for leap years */
DaysPerMonth.3 = 31
DaysPerMonth.4 = 30
DaysPerMonth.5 = 31
DaysPerMonth.6 = 30
DaysPerMonth.7 = 31
DaysPerMonth.8 = 31
DaysPerMonth.9 = 30
DaysPerMonth.10 = 31
DaysPerMonth.11 = 30
DaysPerMonth.12 = 31
/* Split (parse) each input record and fill the DayTemp array with daily temperatures by month */
do ii = 2 to Recs.0
parse var Recs.ii DayNum (ifs) DayTemp.1 (ifs) DayTemp.2 (ifs) DayTemp.3 (ifs) DayTemp.4 ,
(ifs) DayTemp.5 (ifs) DayTemp.6 (ifs) DayTemp.7 (ifs) DayTemp.8 ,
(ifs) DayTemp.9 (ifs) DayTemp.10 (ifs) DayTemp.11 (ifs) DayTemp.12 .
/* For each month, adjust min and max values, and sum up for building average later on */
do jj = 1 to 12
/* Don't process values for day numbers greater that number of days in month */
if ( ii - 1 ) <= DaysPerMonth.jj
then do
if MaxTemp.jj < DayTemp.jj
then MaxTemp.jj = DayTemp.jj
if MinTemp.jj > DayTemp.jj
then MinTemp.jj = DayTemp.jj
AvgTemp.jj = AvgTemp.jj + DayTemp.jj
end /* if ( ii - 1 ) ... */
end /* do jj = 1 to 12 */
end /* do ii = 1 to 12 */
Heading = "User,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"
Maxima = "Max"
Minima = "Min"
Means = "Mean"
/* Build the min, max and average records by appending value by value */
do ii = 1 to 12
Maxima = Maxima || ofs || format( MaxTemp.ii, 2, 1 )
Minima = Minima || ofs || format( MinTemp.ii, 2, 1 )
Means = Means || ofs || format( ( AvgTemp.ii / DaysPerMonth.ii ), 2, 1 )
end
/* Write heading, min, max, and average records */
say Heading
say Maxima
say Minima
say Means
Tip: Don't use single letter variable names, since you cannot search, or search-and-replace such names. I always use double letter variable names for loop variables, or temporary variables, such as ii, jj, kk, etc. These (most probably) never appear in the code in any other context, so searching for, and replacing can be easily done.
I have a variable with a date table that looks like this
* table:
[day]
* number: 15
[year]
* number: 2015
[month]
* number: 2
How do I get the days between the current date and the date above? Many thanks!
You can use os.time() to convert your table to seconds and get the current time and then use os.difftime() to compute the difference. see Lua Wiki for more details.
reference = os.time{day=15, year=2015, month=2}
daysfrom = os.difftime(os.time(), reference) / (24 * 60 * 60) -- seconds in a day
wholedays = math.floor(daysfrom)
print(wholedays) -- today it prints "1"
as #barnes53 pointed out could be off by one day for a few seconds so it's not ideal, but it may be good enough for your needs.
You can use the algorithms gathered here:
chrono-Compatible Low-Level Date Algorithms
The algorithms are shown using C++, but they can be easily implemented in Lua if you like, or you can implement them in C or C++ and then just provide Lua bindings.
The basic idea using these algorithms is to compute a day number for the two dates and then just subtract them to give you the number of days.
--[[
http://howardhinnant.github.io/date_algorithms.html
Returns number of days since civil 1970-01-01. Negative values indicate
days prior to 1970-01-01.
Preconditions: y-m-d represents a date in the civil (Gregorian) calendar
m is in [1, 12]
d is in [1, last_day_of_month(y, m)]
y is "approximately" in
[numeric_limits<Int>::min()/366, numeric_limits<Int>::max()/366]
Exact range of validity is:
[civil_from_days(numeric_limits<Int>::min()),
civil_from_days(numeric_limits<Int>::max()-719468)]
]]
function days_from_civil(y, m, d)
if m <= 2 then
y = y - 1
m = m + 9
else
m = m - 3
end
local era = math.floor(y/400)
local yoe = y - era * 400 -- [0, 399]
local doy = math.modf((153*m + 2)/5) + d-1 -- [0, 365]
local doe = yoe * 365 + math.modf(yoe/4) - math.modf(yoe/100) + doy -- [0, 146096]
return era * 146097 + doe - 719468
end
local reference_date = {year=2001, month = 1, day = 1}
local date = os.date("*t")
local reference_days = days_from_civil(reference_date.year, reference_date.month, reference_date.day)
local days = days_from_civil(date.year, date.month, date.day)
print(string.format("Today is %d days into the 21st century.",days-reference_days))
os.time (under Windows, at least) is limited to years from 1970 and up. If, for example, you need a general solution to also find ages in days for people born before 1970, this won't work. You can use a julian date conversion and subtract between the two numbers (today and your target date).
A sample julian date function that will work for practically any date AD is given below (Lua v5.3 because of // but you could adapt to earlier versions):
local
function div(n,d)
local a, b = 1, 1
if n < 0 then a = -1 end
if d < 0 then b = -1 end
return a * b * (math.abs(n) // math.abs(d))
end
--------------------------------------------------------------------------------
-- Convert a YYMMDD date to Julian since 1/1/1900 (negative answer possible)
--------------------------------------------------------------------------------
function julian(year, month, day)
local temp
if (year < 0) or (month < 1) or (month > 12)
or (day < 1) or (day > 31) then
return
end
temp = div(month - 14, 12)
return (
day - 32075 +
div(1461 * (year + 4800 + temp), 4) +
div(367 * (month - 2 - temp * 12), 12) -
div(3 * div(year + 4900 + temp, 100), 4)
) - 2415021
end
What I am trying to do here is this - I want to give index to only the workdays in each week.
So, if in a week, Monday and Wednesday are holidays, then Tuesday should get 1, Thursday should get 2, Friday should get the index 3. Otherwise, in a normal week without any holidays, Monday should get 1, Tuesday 2, Wednesday 3, and so on ...
Here is the code I have written (I haven't coded in years now, so please pardon the crude approach)
Sheet 'Holidays' contains a list of holidays in the column B starting from row 2
Variable date is the date for which I want to find out the index for
Variable dayOfTheWeek is the number of day of 'date' counted from last Sunday, so if date is a Monday, dayOfTheWeek is 1; if date is Tuesday, dayOfTheWeek is 2, and so on ...
function indexOfWorkdayOfTheWeek (date, dayOfTheWeek, lastSundayDate)
{
var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
var activeCell = activeSheet.getActiveRange();
var activeRow = activeCell.getRowIndex();
var activeColumn = activeCell.getColumn();
var count = 1;
for (var j = 1; j < dayOfTheWeek; j++)
{
var date2 = lastSundayDate.valueOf() + j*86400;
Logger.log('Date ' + j + ' is:' + date2);
Logger.log('Last Sunday is:' + lastSundayDate);
if (holidayOrNot(date2) == true)
{
}
else
{
count = count + 1;
}
}
return count;
}
function holidayOrNot(date2)
{
var holidaysSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Holidays');
var listOfHolidays = holidaysSheet.getSheetValues(2, 2, 95, 1);
var isDateMatch = false;
for (var k = 0; k < 90; k++)
{
if (date2 == listOfHolidays[k].valueOf())
{
isDateMatch = true;
break;
}
else
{
continue;
}
}
return isDateMatch;
}
I think the problem is two-fold here:
The date2 calculation isn't working for some reason (var date2 = lastSundayDate.valueOf() + j*86400;)
The function holidayOrNot is returning false, no matter what, even if it encounters a holiday ... the condition date2 == listOfHolidays[k] isn't working for some reason...
Help would be appreciated!
maybe this method below could help you in your calculations, it returns an integer corresponding to the day of the year so if you apply this to your holidays days and compare to the days of interest it could be a good way to find matches.
here it is, just add these lines outside of any function in your script (so you can use it anywhere) then use it like this :
var d = new Date().getDOY();
Logger.log(d)
Here the method :
Date.prototype.getDOY = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((this - onejan) / 86400000);
}
Assuming that lastSundayDate is being passed around correctly, I see a glaring problem:
lastSundayDate.valueOf().
valueOf() on Date objects returns the primitive value... it looks like you're going for adding a day to the date (86400 seconds * j)? I can't tell what the logic is supposed to be here. But the valueOf() date2 is definitely giving you an integer something like: 1384628769399 (see here).
What you really want to accomplish is something like Date.getDay(), or something similar so that you can add hours, days, etc. to the original Date. This is likely the source of all your problems.
What you can do is read the Mozilla Developer Network documentation on Date objects to see all of the functions on Dates and their uses. You can greatly simplify what you're trying to do by using these functions, instead of doing abstract operations like j * 86400.
It should also be noted that you can do simple operations such as the following, to add 4 hours to the current Date (time):
var myDate = new Date();
Logger.log(myDate); // ~ console.write
var laterDate = new Date(myDate.setHours(myDate.getHours() + 4));
Logger.log(laterDate); // ~ console.write
which gives the following:
[13-11-16 14:13:38:947 EST] Sat Nov 16 14:13:38 GMT-05:00 2013
[13-11-16 14:13:38:954 EST] Sat Nov 16 18:13:38 GMT-05:00 2013
Working with dates can be tricky - but it's always best to use the simplest methods that are available, which are built into the Date objects themselves. There are also numerous other libraries that provide extended functionality for Dates such as Date js.
If you're still running into your problem after attempting to try using methods I displayed above, please run your script and post both the Execution Transcript and the content of the Logger so that I can help you narrow down the issue :)
I have a text file that contains timestamps out of a camera that captures 50 frames per second .. The data are as follows:
1 20931160389
2 20931180407
3 20931200603
4 20931220273
5 20931240360
.
.
50 20932139319
... and so on.
It gives also the starting time of capturing like
Date: **02.03.2012 17:57:01**
The timestamps are in microseconds not in milliseconds, and MATLAB can support only till milliseconds but its OK for me.
Now I need to know the human format of these timestamps for each row..like
1 20931160389 02.03.2012 17:57:01.045 % just an example
2 20931180407 02.03.2012 17:57:01.066
3 20931200603 02.03.2012 17:57:01.083
4 20931220273 02.03.2012 17:57:01.105
5 20931240360 02.03.2012 17:57:01.124
and so on
I tried this:
%Refernce Data
clc; format longg
refTime = [2012,03,02,17,57,01];
refNum = datenum(refTime);
refStr = datestr(refNum,'yyyy-mm-dd HH:MM:SS.FFF');
% Processing data
dn = 24*60*60*1000*1000; % Microseconds! I have changed this equation to many options but nothing was helpful
for i = 1 : size(Data,1)
gzTm = double(Data{i,2}); %timestamps are uint64
gzTm2 = gzTm / dn;
gzTm2 = refNum + gzTm2;
gzNum = datenum(gzTm2);
gzStr = datestr(gzNum,'yyyy-mm-dd HH:MM:SS.FFF'); % I can't use 'SS.FFFFFF'
fprintf('i = %d\t Timestamp = %f\t TimeStr = %s\n', i, gzTm, gzStr);
end;
But I got always strange outputs like
i = 1 Timestamp = 20931160389.000000 TimeStr = **2012-03-08 13:29:28.849**
i = 2 Timestamp = 20931180407.000000 TimeStr = **2012-03-08 13:29:29.330**
i = 3 Timestamp = 20931200603.000000 TimeStr = **2012-03-08 13:29:29.815**
The output time is about some hours late/earlier than the Referenced Time. The day is different.
The time gap between each entry in the array should be nearly 20 seconds..since I have 50 frames per second(1000 millisecond / 50 = 20) ..and the year,month, day,hour,minute and seconds should also indicate the initial time given as reference time because it is about some seconds earlier.
I expect something like:
% just an example
1 20931160389 02.03.2012 **17:57:01.045**
2 20931180407 02.03.2012 **17:57:01.066**
Could one help me please..! Where is my mistake?
It looks like you can work out the number of microseconds between a record and the first record:
usecs = double(Data{i,2}) - double(Data{1,2});
convert that into seconds:
secsDiff = usecs / 1e6;
then add that to the initial datetime you'd calculated:
matDateTime = refNum + secsDiff / (24*60*60);
I need to convert a datenumber to its closest end-of-month date. I found an online link but it is very inefficient for a large matrix (at http://www.mathworks.com/matlabcentral/fileexchange/26374-round-off-dates-and-times). Does Matlab (Financial Toolbox) has an inbuilt function for this? I couldn't find it.
date_in = 734421 ;
somefunction(date_in) --> Sept 2010
Thanks!
Basically, it sounds like you are asking for whether a given date is closer to the preceding or following month. You can greatly simplify the logic involved if you use the functions EOMDAY to find the date for the end of the month and ADDTODATE to shift the current month up or down by one. Here's an example function that takes a date number as input:
function closestString = closest_month(dateNumber)
dateVector = datevec(dateNumber);
daysInMonth = eomday(dateVector(1),dateVector(2));
if dateVector(3) > daysInMonth/2
dateNumber = addtodate(dateNumber,1,'month');
else
dateNumber = addtodate(dateNumber,-1,'month');
end
closestString = datestr(dateNumber,'mmm yyyy');
end
I had some errors in my previous version. Here's the logic incorporated into a function. It also checks for the month and updates accordingly.
function out = roundMonth(dateNumber)
dateVector = datevec(dateNumber);
day = dateVector(3);
month = dateVector(2);
year = dateVector(1);
month = month + sign(day - 15 + double(~(month-2)))...
+ double(~(day-15 + double(~(month-2))));
dateVector(1) = year + double((month-12)==1) - double((1-month)==1);
dateVector(2) = mod(month,12) + 12*double(~mod(month,12));
out = datestr(dateVector,'mmm yyyy');
EXAMPLES:
1.
roundMonth(datenum('10-Oct-2010'))
ans =
Sep 2010
2.
roundMonth(datenum('20-Oct-2010'))
ans =
Nov 2010
3.
roundMonth(datenum('20-Dec-2010'))
ans =
Jan 2011
4.
roundMonth(datenum('10-Jan-2010'))
ans =
Dec 2009