Haskell: count an enum (Days of week) by an int - function

I want to create a function for a calender programm, that does the following:
proceed :: Day -> Int -> Day
> proceed Mon 9
Wed
The function proceed should tell me, what weekday it is in 9 days, if today is Monday.
Now I try this:
data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving Show
next :: Day -> Day
next Mon = Tue
next Tue = Wed
next Wed = Thu
next Thu = Fri
next Fri = Sat
next Sat = Sun
next Sun = Mon
proceed :: Day -> Int -> Day
proceed d a = if a==0 then next d
else proceed (next d) (a-1)
I try :
proceed Mon 9
Thu
But that's wrong, the right answear is Wed!!!!!!!
I don't know where I've made the mistake.

Thanks to bheklilr
if a == 0 then d else proceed (next d) (a-1)
It was only an off by one error!

Related

Returning Dates In A Formatted Format (Iteration)

I am trying to create tabs with each tab name being the date of the start of each week in the year. So, "Jan 01" then "Jan 08" then "Jan 14" etc.
Essentially, taking x date then adding +7 days and returning that value as a date 7 days from x date.
function CreateWeekTabs(){
var TotalsSheet = spreadsheet.getSheetByName("Totals");
var StartingWeek = new Date(TotalsSheet.getRange("B1").getValue()); //Typically always "Jan 01" shwon. Cell Formatting is MMM DD. Cell Value is 01/01/2019
var CurrentWeek = new Date();
var NextWeek = new Date();
spreadsheet.toast("Please wait...","Creating Tabs");
for (var WeekNum = 1;WeekNum <= 2;WeekNum++){
var DayIncrease = 7 - (7 * WeekNum); //Should produce 0,7,14,21,28.... So first iteration won't increase any value from Jan 01.
CurrentWeek.setDate(StartingWeek.getDate()+DayIncrease); //E.g. First Iteration = Jan 01 + 0 = Jan 01; Second Iteration = Jan 01 + 7 = Jan 08;
NextWeek.setDate(CurrentWeek.getDate()+7); //Should be +7 days from CurrentWeek Value.
var WeekSheetName = Utilities.formatDate(NextWeek,spreadsheet.getSpreadsheetTimeZone(),"MMM DD"); //Should return the date formatted.
Logger.log(WeekNum+" - "+WeekSheetName);
}
}
With Each Iteration, I intend to create WorkSheets with the First Date of each Week Starting from Value of CurrentWeek
Eg: Jan 01, Jan 08, Jan 15, Jan 22, Jan 29, Feb 05, etc...
UPDATE:
I since changed the code to:
function CreateWeekTabs(){
var TotalsSheet = spreadsheet.getSheetByName("Totals");
var CurrentWeek = new Date(TotalsSheet.getRange("B1").getValue()); //Typically always "Jan 01" shown. Cell Formatting is MMM dd. Cell Value is 01/01/2019
// var CurrentWeek = new Date();
var NextWeek = new Date();
spreadsheet.toast("Please wait...","Creating Tabs");
for (var WeekNum = 1;WeekNum <= 12;WeekNum++){
var DayIncrease = (7 * WeekNum) - 7; //Should produce 0,7,14,21,28.... So first iteration won't increase any value from Jan 01.
CurrentWeek.setDate(CurrentWeek.getDate()+DayIncrease); //E.g. First Iteration = Jan 01 + 0 = Jan 01; Second Iteration = Jan 01 + 7 = Jan 08;
NextWeek.setDate(CurrentWeek.getDate()+DayIncrease+7); //Should be +7 days from CurrentWeek Value.
var WeekSheetName = Utilities.formatDate(NextWeek,spreadsheet.getSpreadsheetTimeZone(),"MMM dd"); //Should return the date formatted.
Logger.log("Week Number: "+WeekNum+" - Current Week: "+Utilities.formatDate(CurrentWeek,spreadsheet.getSpreadsheetTimeZone(),"MMM dd")+" Next Week: "+WeekSheetName);
}
}
and the Log is producing the following as outputs. (so I can see what it's producing for Variables 'CurrentWeek' and 'NextWeek'
[19-06-14 14:40:00:463 EDT] Week Number: 1 - Current Week: Jan 01 Next Week: Jun 08
[19-06-14 14:40:00:464 EDT] Week Number: 2 - Current Week: Jan 08 Next Week: Jun 22
[19-06-14 14:40:00:464 EDT] Week Number: 3 - Current Week: Jan 22 Next Week: Jul 13
[19-06-14 14:40:00:465 EDT] Week Number: 4 - Current Week: Feb 12 Next Week: Aug 09
[19-06-14 14:40:00:466 EDT] Week Number: 5 - Current Week: Mar 12 Next Week: Sep 16
[19-06-14 14:40:00:467 EDT] Week Number: 6 - Current Week: Apr 16 Next Week: Oct 28
[19-06-14 14:40:00:468 EDT] Week Number: 7 - Current Week: May 28 Next Week: Dec 16
[19-06-14 14:40:00:468 EDT] Week Number: 8 - Current Week: Jul 16 Next Week: Feb 10
[19-06-14 14:40:00:469 EDT] Week Number: 9 - Current Week: Sep 10 Next Week: Apr 13
[19-06-14 14:40:00:470 EDT] Week Number: 10 - Current Week: Nov 12 Next Week: Jun 21
[19-06-14 14:40:00:471 EDT] Week Number: 11 - Current Week: Jan 21 Next Week: Sep 06
[19-06-14 14:40:00:471 EDT] Week Number: 12 - Current Week: Apr 07 Next Week: Nov 30
Why the blazes? Current Value is calculating correctly, but the value of Next Week is way off, it should be showing +7 days from Current Week.
Try these:
The first calculates the start of week tab name for this week. You can pick the start of week day Sun-Sat is 0-6. The second calculates the start of week tab name for next week.
function thisWeeksStartOfWeekTabname(sow){
var sow=sow || 1;//Sun-0, Sat=6
var ss=SpreadsheetApp.getActive();
var dt=new Date();
while(dt.getDay()>0) {
dt=new Date(dt.setDate(dt.getDate()-1));
}
dt=new Date(dt.setDate(dt.getDate()+sow));
Logger.log(Utilities.formatDate(dt, Session.getScriptTimeZone(), "MMM dd"));
return Utilities.formatDate(dt, Session.getScriptTimeZone(), "MMM dd");
}
function nextWeeksStartOfWeekTabname(sow){
var sow=sow || 1;//Sun-0, Sat=6
var ss=SpreadsheetApp.getActive();
var dt=new Date();
while(dt.getDay()>0) {
dt=new Date(dt.setDate(dt.getDate()+1));
}
dt=new Date(dt.setDate(dt.getDate()+sow));
Logger.log(Utilities.formatDate(dt, Session.getScriptTimeZone(), "MMM dd"));
return Utilities.formatDate(dt, Session.getScriptTimeZone(), "MMM dd");
}

Get date without offset

I'm using MySQL to store my data. I'm recorded dates with different offset according to each timezone. What is important on those dates are only "effective" time. Here is an example:
date1 = "Thu, 27 Oct 2016 07:00:00 CEST +02:00"
# I want to get 700
date2 = "Thu, 27 Oct 2016 22:00:00 CEST +02:00"
# I want to get 2200
I would like to get these values to compare them with my current time. Then if it's currently "2016-11-17 10:12:00 +0100", I would like to compare on a where clause:
"1012" > "2200"
# or
"1012" > "700"
Here is a fake record value:
# my_table
# | id | my_hour
# | XX | "Thu, 27 Oct 2016 07:00:00 CEST +02:00"
# | XY | "Thu, 27 Oct 2016 22:00:00 CEST +11:00"
Here is my code:
hour = Time.zone.now
# "2016-11-18 21:10:00 +0100"
where("CAST(DATE_FORMAT(my_hour,'%H%i') AS UNSIGNED) < ?", hour.strftime("%H%M").to_i)
# => Get XX record?
Use strftime to format date in Rails.
hour = Time.zone.now
MyTable.where("cast(strftime('%H%M', my_hour) as int) < ?", hour.strftime("%H%M").to_i)
here MyTable is your Model, my_hour is your date column and hour is current time.

To get values from 2D array

I have used this query to retrieve the dates for one particular user's approved leaves -
LeaveRequest.where(user_id: 6).where(status: 1).pluck(:from_date, :to_date)
and I'm getting this array as result -
[[Mon, 12 Sep 2016, Fri, 16 Sep 2016], [Tue, 06 Sep 2016, Tue, 06 Sep 2016], [Thu, 01 Sep 2016, Fri, 02 Sep 2016], [Tue, 30 Aug 2016, Wed, 31 Aug 2016]]
what I want is to fetch all the dates as well as the dates between 12 Sep 2016 and 16 Sep, 2016 (13th 14th and 15th).
I am assuming you mean something like this
require 'date'
#This is to simulate your current Array
current_array = 5.times.map {|n [Date.new(2016,n+1,1).<<(1),Date.new(2016,n+1,1)]}
#map the 2 dates to a Range
new_array = current_array.map{|start_date,end_date| (start_date..end_date)}
new_array.first.class
#=> Range
Calling to_a on the Range will blow it out into all the dates between start_date and end_date
With a rails you could do something like
class LeaveRequest
def self.user_requested_ranges(user_id, status_id)
scoped.
where(user_id: user_id, status: status_id).
pluck(:from_date, :to_date).
map do |from_date, to_date|
#optionally to output the full Array in each Range you could use
#(from_date..to_date).to_a
(from_date..to_date)
end
end
end
Then call as
LeaveRequest.user_requested_ranges(6,1)

How to Display 4week per month with condition in sql

I have this logic but I cant figure out what to do to come up with the results. I want to achieve the results below, the idea is (Ex. month of October 2014), normally it has 5 weeks. If there is a 5th week and days is greater than 3 then consider whole week in the next month else add it to 4th week.
Input:
date range
from: 10-01-2014
to: 11-30-2014
Sample Output:
Date Customer week# Dates covered
10-01-2014 Cust01 1 Oct 01 - Oct 11, 2014
10-08-2014 Cust02 1 Oct 01 - Oct 11, 2014
10-17-2014 Cust02 2 Oct 12 - Oct 18, 2014
10-25-2014 Cust03 3 Oct 19 - Oct 25, 2014
10-31-2014 Cust01 4 Oct 26 - Oct 31, 2014
11-01-2014 Cust01 1 Nov 01 - Nov 08, 2014
11-28-2014 Cust02 4 Nov 23 - Nov 30, 2014
11-30-2014 Cust05 4 Nov 23 - Nov 30, 2014
Thanks
Use datepart(ww,[date]) to get week number in a year, then compare the week number by the begin date of a month.
Below is the detail approach to calculate for one date:
declare #dt date, #month_begin date, #month_end date, #week_of_month int
set #dt='20141031'
set #month_begin = convert(date,(convert(char(6),#dt,112)+'01'))
set #month_end = dateadd(day, -1, dateadd(month,1,#month_begin))
set #week_of_month = datepart(ww,#dt) - datepart(ww,convert(date,(convert(char(6),#dt,112)+'01'))) + 1
select
case when #week_of_month > 4 and datepart(dw,#month_end)>3
then 1
else #week_of_month
end as week,
case when #week_of_month > 4 and datepart(dw,#month_end)>3
then datepart(month,dateadd(month,1,#dt))
else datepart(month,#dt)
end as month

Dealing with empty cells in Google Apps Script

Why doesn't this work?
function sendDuesReminder() {
var paid = 3;
var name = 1;
var submitted = 0;
var allowance = 9;
var ms = 86400000; // Number of milliseconds in a day
var today = new Date();
var reminder = 72;
var data = SpreadsheetApp.openById('___').getSheetByName('Master').getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
if (data[i][paid] != 'Yes' &&
data[i][paid] != 'yes' &&
data[i][reminder] == '' &&
((((today.valueOf()) - (data[i][submitted].valueOf()))/ms) > allowance)) {
MailApp.sendEmail("___", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
if (data[i][paid] != 'Yes' &&
data[i][paid] != 'yes' &&
data[i][reminder] != null &&
((((today.valueOf()) - (data[i][reminder].valueOf()))/ms) > allowance)) {
MailApp.sendEmail("___", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
SpreadsheetApp.flush();
}
Browser.msgBox("OK. Reminder e-mails have been sent. !")
}
What I really want to do is say send the e-mail if column BT is empty OR if the date in column BT is older than 9 days. But I didn't know how to include an or statement within the if statement. So I just set up two separate if statements.
When I use '', though, for the second if statement, I get an error saying that it can't get the value of something that's undefined.
When I use null or undefined, it doesn't work.
Anybody have any thoughts?
Are you sure you have 72 columns in your spreadsheet ? when you use data[i][reminder] == '' the error returned concerns the first term of the equal, not the second... so I guess data doesn't have 72 secondary index and this is returning an error.
(EDIT : to be more clear : you cannot get the value of an undefined item using .valueOf and divide it by something, that's why you get "an error saying that it can't get the value of something that's undefined ".)
If you want to learn about how to implement OR statement you can have a look at w3school, 'Comparison Operators'
Note that you can compare date object directly, you don't need to convert them to milliseconds explicitely, javascript does it internally.
here is an example of how you could write this shortly
var tendaysBefore = new Date(new Date().getTime()-10*24*60*60*1000);// 10 days before
if (data[i][paid].toLowerCase() != 'yes' && (data[i][reminder] == ''||(data[i][reminder] == null || data[i][submitted]< tendaysBefore)) { // not 'yes' and one of the 3 other conditions
MailApp.sendEmail("___", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
So here's the code for the loop I tried based on Serge's very kind initial thought.
for (var i = 1; i < data.length; i++) {
if (data[i][paid].toLowerCase() != 'yes' &&
(data[i][submitted]<tendaysBefore &&
(data[i][reminder] == ''||
data[i][reminder] == null))) {
MailApp.sendEmail("___", "Reminder About Dues for Newcomers & Neighbors", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
SpreadsheetApp.flush();
}
I changed the order of the if statement because I'm not sure I've adequately articulated in English what I'm trying to get it to do.
What I WANT it to say is IF they haven't paid AND 10 days have passed since they submitted their form AND EITHER the reminder cell is blank or has a null value, THEN send the e-mail.
(Once I get THIS statement working, I'll go on to say if 10 days go by after we send the first e-mail and they STILL haven't paid, we send another e-mail. That's why I'm going through all this machination to put a date in reminder rather than just something like "sent".)
The code I have works. EXCEPT, if you run it, send out the first batch of e-mails, let it add today's date to reminder, and then run it again, it sends the e-mails out all over again.
In short,
(data[i][reminder] == ''||
data[i][reminder] == null))
doesn't seem to be accomplishing what is supposed to do, which is make the if statement fail for any row that has ANYTHING in the reminder column. That's why I initially came at this with "how do I deal with empty cells"? Because--for the life of me, I can't understand why
(data[i][reminder] == ''||
data[i][reminder] == null))
isn't bulletproof.
As I suggested in my comment to Serge's answer, this is starting to make me crazy. I, therefore, cannot thank anybody enough for ANY thoughts you have. Thanks in advance!
In response to Serge's question that I capture some values from the log, here's the output from the log after I added his requested code to the loop:
Paid=yes date subm=Sat Jun 02 2012 14:44:27 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=Wed Jun 27 2012 16:22:35 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Fri Jun 29 2012 09:07:21 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 10:11:20 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 10:16:56 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 10:17:00 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 10:26:36 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 10:30:23 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 11:02:19 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 12:33:57 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 13:48:54 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 18:19:22 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 21:07:05 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 21:44:13 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 21:53:55 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Tue Jul 10 2012 11:09:03 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Tue Jul 10 2012 12:57:41 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Wed Jul 11 2012 18:36:49 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Thu Jul 12 2012 07:14:53 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Tue Jul 17 2012 14:54:16 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Wed Jul 18 2012 20:26:23 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Thu Jul 19 2012 13:43:09 GMT-0400 (EDT)reminder=undefined
I have no idea what to make of this, but I'm sure smarter people than I do see something interesting here?
OK, following Serge's diligent trouble shooting with me, here's the code that worked for this problem. Many, MANY thanks to Serge!
function sendDuesReminder() {
var paid = 3;
var name = 1;
var submitted = 0;
var allowance = 9;
var ms = 86400000; // Number of milliseconds in a day
var today = new Date();
var reminder = 72;
var reminderArray = reminder - 1;
var tendaysBefore = new Date(new Date().getTime()-10*24*60*60*1000);
var data = SpreadsheetApp.openById('___').getSheetByName('Master').getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
if (data[i][paid].toLowerCase() != 'yes' &&
(data[i][submitted]<tendaysBefore &&
(data[i][reminderArray] == ''||
data[i][reminderArray] == null))) {
MailApp.sendEmail("___", "___", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
SpreadsheetApp.flush();
Logger.log('Paid='+data[i][paid].toLowerCase()+' date subm='+data[i][submitted]+'reminder='+data[i][reminder])
}
Browser.msgBox("OK. Reminder e-mails have been sent. !")
}