I am new to Access 2010 and need to get the number of days in a workweek excluding Holidays however with a twist. I have been able to use the standard VB code for workdays that appears on the internet and it works great for a simple Monday – Friday or Monday - Saturday calculation. My question is, how can I or is it possible to manipulate this code to calculate the number of days if Friday, Saturday and Sunday all count as 1 day?
Example: Calculate the number of days from Tuesday 11/25/14 to today.
-Today's date = Monday, December 01, 2014;
-Monday, December 01, 2014 = 0;
-Sunday, November 30, 2014 = 3;
-Saturday, November 29, 2014 = 3;
-Friday, November 28, 2014 = 3;
-Thursday, November 27, 2014(Holiday) = 2;
-Wednesday, November 26, 2014 = 2;
-Tuesday, November 25, 2014 = 1
So in the example above, the number of days would be 3.
If you need to account for Statutory Holidays you'll really need to use some kind of table. Purely algorithmic approaches to the problem are difficult to manage and prone to failure, primarily because
Holidays that fall on a fixed date may be observed on some other date. For example, if Christmas falls on a Saturday then employees may get a day off on Friday.
Some holiday dates are difficult to calculate. In particular, Good Friday is defined (here in Canada, at least) as "the Friday before the first Sunday after the first full moon following the Spring Equinox".
In its simplest form, the [DatesTable] could look something like this:
theDate dayOff comment
---------- ------ ----------------
2014-11-21 False
2014-11-22 True Saturday
2014-11-23 True Sunday
2014-11-24 False
2014-11-25 False
2014-11-26 False
2014-11-27 True Thanksgiving Day
2014-11-28 False
2014-11-29 True Saturday
2014-11-30 True Sunday
2014-12-01 False
2014-12-02 False
Counting the number of work days between 2014-11-25 and 2014-11-30 (inclusive) would simply be
SELECT COUNT(*) AS WorkDays
FROM DatesTable
WHERE theDate Between #2014-11-25# And #2014-11-30#
AND dayOff=False;
Related
I am trying to create a cumulative time variable for an NBA shot log dataset which will combine three different measurements for the passage of time. I need to use 12-Game Clock in order to determine the time of a shot for a given NBA player since a quarter in the NBA is 12 minutes. Following the same logic, a shot in the second quarter with a game clock of 11:00 would correspond to a cumulative time of 12+(12-11)= 13 minutes. AM/PM does not exist in the game clock variable- it simply represents how many minutes and seconds have passed in the quarter.
Date
Quarter
Game Clock (Min:Sec)
OCT 29, 2014
1
11:01
OCT 29, 2014
3
2:42
OCT 30, 2014
1
1:58
NOV 01, 2014
2
1:15
Desired Output:
Cumulative Time
00:00:59
00:45:58
24:10:02
72:34:45
Please let me know if you need more information. Dataset: https://www.kaggle.com/dansbecker/nba-shot-logs
Thank you in advance.
#tedscr working with times-only can be confusing in R. The package {lubridate} comes with 3 different types, i.e. interval, duration, and periods. For the following I am using the {hms} packages that helps with formatting and parsing times and working with it as a period (:= hms independent of a [start]date).
Note: Under the hood, we work with seconds. Thus, you could also coerce all you have to numerical seconds or difftime and work with this.
To explain to you what is happening, I create a new column for each step.
You may want to combine this in a single operation to your liking.
library(hms)
library(lubridate)
library(dplyr)
#----------------------- data -----------------------------
nba <- tibble::tribble(
~Date, ~Quarter, ~`Game.Clock.(Min:Sec)`,
"OCT 29, 2014", 1L, "11:01",
"OCT 29, 2014", 3L, "2:42",
"OCT 30, 2014", 1L, "1:58",
"NOV 01, 2014", 2L, "1:15"
)
quarter <- hms::hms(minutes = 12) # to create a "period" of 12 minutes
nba %>%
mutate(
#---- determine the time played in the current quarter
#---- as Game.Clock is a character emulating mm::ss add 00: to have hms!
GameClockPlayed = quarter - hms::parse_hms(paste0("00:", `Game.Clock.(Min:Sec)`) )
#---- simply add the previous quarters played to the current played time
#---- note: this returns "seconds"
, CumGameClock = (Quarter * quarter) + GameClockPlayed
#---- use lubridate to nicely format the seconds played
, CumGameClock2 = lubridate::seconds_to_period(CumGameClock))
)
This gives you:
Date Quarter `Game.Clock.(Min:Sec)` GameClockPlayed CumGameClock CumGameClock2
<chr> <int> <chr> <drtn> <drtn> <Period>
1 OCT 29, 2014 1 11:01 59 secs 779 secs 12M 59S
2 OCT 29, 2014 3 2:42 558 secs 2718 secs 45M 18S
3 OCT 30, 2014 1 1:58 602 secs 1322 secs 22M 2S
4 NOV 01, 2014 2 1:15 645 secs 2085 secs 34M 45S
If you need to do further math and the hms/lubirdate period construction is too cumbersome, you can apply as.numeric() to your period object. Likewise for the final presentation, you can coerce it back to the character formatting.
Hello I am trying to find the week number for a series of date over three years. However R is not giving the correct week number. I am generating a seq of dates from 2016-04-01 to 2019-03-30 and then I am trying to calculate week over three years such that I get the week number 54, 55 , 56 and so on.
However when I check the week 2016-04-03 R shows the week number as 14 where as when cross checked with excel it is the week number 15 and also it simply calculates 7 days and does not reference the actual calendar days. Also the week number starts from 1 for every start of year
The code looks like this
days <- seq(as.Date("2016-04-03"),as.Date("2019-03-30"),'days')
weekdays <- data.frame('days'=days, Month = month(days), week = week(days),nweek = rep(1,length(days)))
This is how the results looks like
days week
2016-04-01 14
2016-04-02 14
2016-04-03 14
2016-04-04 14
2016-04-05 14
2016-04-06 14
2016-04-07 14
2016-04-08 15
2016-04-09 15
2016-04-10 15
2016-04-11 15
2016-04-12 15
However when checked from excel this is what I get
days week
2016-04-01 14
2016-04-02 14
2016-04-03 15
2016-04-04 15
2016-04-05 15
2016-04-06 15
2016-04-07 15
2016-04-08 15
2016-04-09 15
2016-04-10 16
2016-04-11 16
2016-04-12 16
Can someone please help me identify wherever I am going wrong.
Thanks a lot in advance!!
Not anything that you're doing wrong per se, there is just a difference in how R (I presume you're using the lubridate package) and Excel calculate week numbers.
R will calculate week numbers based on the seven day block from 1 January that year; but
Excel calculates week numbers based on a week starting from Sunday.
Taking the first few days of January 2016 for an example. On, Friday, 1 January 2016, both R and Excel will say this is week 1.
On Sunday, 3 January 2016:
this is within the first seven days of the start of the year so R will return week number 1; but
it is a Sunday, so Excel ticks over to week number 2.
Try this:
ifelse(test = weekdays.Date(days[1]) == "Sunday", yes = epiweek(days[1]), no = epiweek(days[1]) + 1) + cumsum(weekdays.Date(days) == "Sunday")
This tests whether the first day is a Sunday or not and returns an appropriate week number starting point, then adds on one more week number each Sunday. Gives the same week number if there's overlap between years.
I'm trying to define a custom week for a dataframe.
I have a dataframe with timestamps.
I've read the questions on here regarding isocalendar. While it does the job. It's not what I want.
I'm trying to define the weeks from Friday to Thrusday.
For example:
Friday 2nd Jan 2015 would be the first day of the week.
Thursday 8th Jan 2015 would be the last day of the week.
And this would be week 1.
Is there a way to set a custom weekday? so when I access the the datetime library, I get the result that I expect.
df['Week_Number'] = df['Date'].dt.week
Here's one solution - convert your dates to a Period representing weeks that end on Thursday.
In [39]: df = pd.DataFrame({'Date':pd.date_range('2015-1-1', '2015-12-31')})
In [40]: df['Period'] = df['Date'].dt.to_period('W-THU')
In [41]: df['Week_Number'] = df['Period'].dt.week
In [44]: df.head()
Out[44]:
Date Period Week_Number
0 2015-01-01 2014-12-26/2015-01-01 1
1 2015-01-02 2015-01-02/2015-01-08 2
2 2015-01-03 2015-01-02/2015-01-08 2
3 2015-01-04 2015-01-02/2015-01-08 2
4 2015-01-05 2015-01-02/2015-01-08 2
Note that it follows the same convention as datetimes, where week 1 can be incomplete, so you may have to do a little extra munging if you want 1 to be the first complete week.
In RadScheduler [TimeLine View], I have a StartDate = 1st Jan 2014 and EndDate = 30th April 2014 [both inclusive] and I have set the SlotDuration = 31 days.
I need to display 4 (January, February, March, April) slots [i.e. Number Of Slots = no of months between StartDate and EndDate taking above Dates into consideration] in TimeLine View and SlotDuration for each slot needs to be no. of days present in that month.
For January, SlotDuration = 31 [because January has 31 days]
February, SlotDuration = 28 [because February has 28 days or 29 if it's a Leap Year]
March, SlotDuration = 31 [because March has 31 days]
April, SlotDuration = 30 [because April has 30 days]
Case 1:
When I plot an appointment from 1 March 2014 to 31 March 2014, it should start and end in March slot but it starts from February slot because we have set SlotDuration = 31 days and February 2014 has only 28 days.
To fulfill 31 days slot duration, 1st, 2nd and 3rd of March are pushed to February 2014 slot.
Case 2:
When I plot an appointment from 4 March 2014 to 31 March 2014 it starts from March slot which is correct. But March slot also contains 1st, 2nd, and 3rd of April to fulfill 31 days slot duration.
My question is how do I make SlotDuration dynamic for each slot?
Currently, For Case 1 RadScheduler displays my appointment like in TimeLineMonth_Incorrect.png but i want to display it as in TimeLineMonth_Correct.png
Is there a good way to get a year + week number converted a date in R? I have tried the following:
> as.POSIXct("2008 41", format="%Y %U")
[1] "2008-02-21 EST"
> as.POSIXct("2008 42", format="%Y %U")
[1] "2008-02-21 EST"
According to ?strftime:
%Y Year with century. Note that whereas there was no zero in the
original Gregorian calendar, ISO 8601:2004 defines it to be valid
(interpreted as 1BC): see http://en.wikipedia.org/wiki/0_(year). Note
that the standard also says that years before 1582 in its calendar
should only be used with agreement of the parties involved.
%U Week of the year as decimal number (00–53) using Sunday as the
first day 1 of the week (and typically with the first Sunday of the
year as day 1 of week 1). The US convention.
This is kinda like another question you may have seen before. :)
The key issue is: what day should a week number specify? Is it the first day of the week? The last? That's ambiguous. I don't know if week one is the first day of the year or the 7th day of the year, or possibly the first Sunday or Monday of the year (which is a frequent interpretation). (And it's worse than that: these generally appear to be 0-indexed, rather than 1-indexed.) So, an enumerated day of the week needs to be specified.
For instance, try this:
as.POSIXlt("2008 42 1", format = "%Y %U %u")
The %u indicator specifies the day of the week.
Additional note: See ?strptime for the various options for format conversion. It's important to be careful about the enumeration of weeks, as these can be split across the end of the year, and day 1 is ambiguous: is it specified based on a Sunday or Monday, or from the first day of the year? This should all be specified and tested on the different systems where the R code will run. I'm not certain that Windows and POSIX systems sing the same tune on some of these conversions, hence I'd test and test again.
Day-of-week == zero in the POSIXlt DateTimesClasses system is Sunday. Not exactly Biblical and not in agreement with the R indexing that starts at "1" convention either, but that's what it is. Week zero is the first (partial) week in the year. Week one (but day of week zero) starts with the first Sunday. And all the other sequence types in POSIXlt have 0 as their starting point. It kind of interesting to see what coercing the list elements of POSIXlt objects do. The only way you can actually change a POSIXlt date is to alter the $year, the $mon or the $mday elements. The others seem to be epiphenomena.
today <- as.POSIXlt(Sys.Date())
today # Tuesday
#[1] "2012-02-21 UTC"
today$wday <- 0 # attempt to make it Sunday
today
# [1] "2012-02-21 UTC" The attempt fails
today$mday <- 19
today
#[1] "2012-02-19 UTC" Success
I did not come up with this myself (it's taken from a blog post by Forester), but nevertheless I thought I'd add this to the answer list because it's the first implementation of the ISO 8601 week number convention that I've seen in R.
No doubt, week numbers are a very ambiguous topic, but I prefer an ISO standard over the current implementation of week numbers via format(..., "%U") because it seems that this is what most people agreed on, at least in Germany (calendars etc.).
I've put the actual function def at the bottom to facilitate focusing on the output first. Also, I just stumbled across package ISOweek, maybe worth a try.
Approach Comparison
x.days <- c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
x.names <- sapply(1:length(posix), function(x) {
x.day <- as.POSIXlt(posix[x], tz="Europe/Berlin")$wday
if (x.day == 0) {
x.day <- 7
}
out <- x.days[x.day]
})
data.frame(
posix,
name=x.names,
week.r=weeknum,
week.iso=ISOweek(as.character(posix), tzone="Europe/Berlin")$weeknum
)
# Result
posix name week.r week.iso
1 2012-01-01 Sun 1 4480458
2 2012-01-02 Mon 1 1
3 2012-01-03 Tue 1 1
4 2012-01-04 Wed 1 1
5 2012-01-05 Thu 1 1
6 2012-01-06 Fri 1 1
7 2012-01-07 Sat 1 1
8 2012-01-08 Sun 2 1
9 2012-01-09 Mon 2 2
10 2012-01-10 Tue 2 2
11 2012-01-11 Wed 2 2
12 2012-01-12 Thu 2 2
13 2012-01-13 Fri 2 2
14 2012-01-14 Sat 2 2
15 2012-01-15 Sun 3 2
16 2012-01-16 Mon 3 3
17 2012-01-17 Tue 3 3
18 2012-01-18 Wed 3 3
19 2012-01-19 Thu 3 3
20 2012-01-20 Fri 3 3
21 2012-01-21 Sat 3 3
22 2012-01-22 Sun 4 3
23 2012-01-23 Mon 4 4
24 2012-01-24 Tue 4 4
25 2012-01-25 Wed 4 4
26 2012-01-26 Thu 4 4
27 2012-01-27 Fri 4 4
28 2012-01-28 Sat 4 4
29 2012-01-29 Sun 5 4
30 2012-01-30 Mon 5 5
31 2012-01-31 Tue 5 5
Function Def
It's taken directly from the blog post, I've just changed a couple of minor things. The function is still kind of sketchy (e.g. the week number of the first date is far off), but I find it to be a nice start!
ISOweek <- function(
date,
format="%Y-%m-%d",
tzone="UTC",
return.val="weekofyear"
){
##converts dates into "dayofyear" or "weekofyear", the latter providing the ISO-8601 week
##date should be a vector of class Date or a vector of formatted character strings
##format refers to the date form used if a vector of
## character strings is supplied
##convert date to POSIXt format
if(class(date)[1]%in%c("Date","character")){
date=as.POSIXlt(date,format=format, tz=tzone)
}
# if(class(date)[1]!="POSIXt"){
if (!inherits(date, "POSIXt")) {
print("Date is of wrong format.")
break
}else if(class(date)[2]=="POSIXct"){
date=as.POSIXlt(date, tz=tzone)
}
print(date)
if(return.val=="dayofyear"){
##add 1 because POSIXt is base zero
return(date$yday+1)
}else if(return.val=="weekofyear"){
##Based on the ISO8601 weekdate system,
## Monday is the first day of the week
## W01 is the week with 4 Jan in it.
year=1900+date$year
jan4=strptime(paste(year,1,4,sep="-"),format="%Y-%m-%d")
wday=jan4$wday
wday[wday==0]=7 ##convert to base 1, where Monday == 1, Sunday==7
##calculate the date of the first week of the year
weekstart=jan4-(wday-1)*86400
weeknum=ceiling(as.numeric((difftime(date,weekstart,units="days")+0.1)/7))
#########################################################################
##calculate week for days of the year occuring in the next year's week 1.
#########################################################################
mday=date$mday
wday=date$wday
wday[wday==0]=7
year=ifelse(weeknum==53 & mday-wday>=28,year+1,year)
weeknum=ifelse(weeknum==53 & mday-wday>=28,1,weeknum)
################################################################
##calculate week for days of the year occuring prior to week 1.
################################################################
##first calculate the numbe of weeks in the previous year
year.shift=year-1
jan4.shift=strptime(paste(year.shift,1,4,sep="-"),format="%Y-%m-%d")
wday=jan4.shift$wday
wday[wday==0]=7 ##convert to base 1, where Monday == 1, Sunday==7
weekstart=jan4.shift-(wday-1)*86400
weeknum.shift=ceiling(as.numeric((difftime(date,weekstart)+0.1)/7))
##update year and week
year=ifelse(weeknum==0,year.shift,year)
weeknum=ifelse(weeknum==0,weeknum.shift,weeknum)
return(list("year"=year,"weeknum"=weeknum))
}else{
print("Unknown return.val")
break
}
}