Get name of day from month, year, and day - language-agnostic

Does anyone know a way to convert a month, year, and day into the day's name for any year? Example:
function convert(day, year, month)
...
return "Monday"
end
Thanks in advance!

You can use the following method:
This method uses codes for different
months and years to speed up the
calculation of the day of the week.
You might even be able to memorize the
codes. We'll use December 16, 2482 as
an example.
Take the last 2 digits of the year. In
our example, this is 82.
Divide by 4, and drop any remainder.
82 / 4 = 20, remainder 2, so we think
"20."
Add the day of the month. In our
example, 20 + 16 = 36.
Add the month's key value, from the
following table. Jan Feb Mar Apr May
June July Aug Sept Oct Nov Dec 1 4 4
0 2 5 0 3 6 1 4 6
The month for our example is December,
with a key value of 6. 36 + 6 = 42.
If your date is in January or February
of a leap year, subtract 1. We're
using December, so we don't have to
worry about this step.
Add the century code from the
following table. (These codes are for
the Gregorian calendar. The rule's
slightly simpler for Julian dates.)
1700s 1800s 1900s 2000s 4 2 0 6
Our example year is 2482, and the
2400s aren't in the table. Luckily,
the Gregorian calendar repeats every
four hundred years. All we have to do
is add or subtract 400 until we have a
date that is in the table. 2482 - 400
= 2082, so we look at the table for the 2000s, and get the code 6. Now we
add this to our running total: 42 + 6
= 48.
Add the last two digits of the year.
48 + 82 = 130.
Divide by 7 and take the remainder.
This time, 1 means Sunday, 2 means
Monday, and so on. A remainder of 0
means Saturday.
How to calculate the day of the week

A quickl google for "day of week from date algorithm" showed up this Wikipedia article
But depending on the dates you need to work with, beware the strange history of Gregorian calendar adoption

Related

Grouping by Month i.e. 30 days from the starting timestamp rather than the actual month

I have a monthly offering that gives customers 30 minutes of use every month and I need to tally up their usage and group it by month, but not sure the best way to handle that since the start date could be any day of the month.
Should I prorate? Convert into full months or count the days?
Is there an ideal way to tally this? Let's say each month they get 30 minutes of use time, so I want to tally how many minutes were used that "month."
Say there is a minutes used table and the start date for the subscription is 2019-06-13 00:00:00
minutes_used_table:
Userid MinutesUsed Date
1 5 2019-06-19
1 6 2019-06-23
1 8 2019-06-28
1 15 2019-07-05
1 3 2019-07-12
1 8 2019-07-19
1 5 2019-08-14
1 3 2019-08-22
1 1 2019-08-26
1 2 2019-09-13
Or, should I prorate it and instead of tracking in 30 day increments, if they start on the 13th of June, should I just count the days from the start date to the end of the month, whatever day that is and then the days from the first of the month until the start date?
Wondering what makes the most sense and how to carry it out?
Use
GROUP BY DATEDIFF(`Date`, #starting_date) DIV #period_length
In your particular case it will be
GROUP BY DATEDIFF(`Date`, '2019-06-13 00:00:00') DIV 30
From coding point of view it's not a big deal to find first date for user, subtract it from dates and count number of 30-days periods.
But this will be very hard to support in future and this solution will have a number of corner cases: for example someone first start to use product at 20 January, after month of usage have been idle for a while and came back in April, 5. What will be right start date for that case?
So I suggest to use calendar months. And may be reduce limit on first month accordingly to the number of days left or give full trial period even on first month as user has ability to spend 30 minutes.

Find date scope from MySQL efficiently

Here is my DiscountPeriod table's structure:
id
room_id
date_from
date_last
discount
Imagine that we have discount starting 01 December 2017 and ending in in 10 December 2017.
I'm searching for date-range to see if it has discount.
So date range might be totally or partly inside some of discount periods. 3 example date-ranges for search:
From 02 December to 10 December (fully inside one of discount periods)
From 20 November to 4 December (partly inside)
From 5 December to 15 December (partly inside)
Expected for all of 3 examples above is to get discount that starts in 01 December 2017 and ends in 10 December 2017.
Currently my query takes only those results which is completely inside exact period from database.
It looks like this:
SELECT * FROM `DiscountPeriod` WHERE (`room_id`=1517) AND (`date_last` >= '2017-12-12') AND (`date_from` <= '2017-12-20');
Question is, how to fit all of 3 possible search cases into 1 query for efficient searching in MySQL database tables?
Expected result is
All of following scopes: From 02 Dec to 10 Dec, From 20 Nov to 4 Dec, From 5 Dec to 15 Dec should return back 1-10 december discount.
This looks like an overlapping range problem. If you want to return all discounts which overlap with 1-10 December 2017, then try the following query:
SELECT *
FROM DiscountPeriod
WHERE
room_id = 1517 AND
'2017-12-01' <= date_last AND '2017-12-10' >= date_from;
Here is a demo which uses your test data. All three discount ranges you suggested show up in the result set. But a range lying completely outside 1-10 December 2017 is absent, as we would expect.
Demo

working days calculation query - working but not able to understand

I wanted to calculate number of working days for an year (excluding only saturdays and sundays) and got this query from web and its working..but i am not able to understand this query from MID part..can anyone help me to understand this...
SELECT 5 * (DATEDIFF('2015-12-31', '2015-01-01') DIV 7) +
MID('0123444401233334012222340111123400012345001234550', 7 * WEEKDAY('2015-12-31') +
WEEKDAY('2015-01-01') + 1, 1)
i am not able to understand from
MID('0123444401233334012222340111123400012345001234550', 7 * WEEKDAY('2015-12-31') +
WEEKDAY('2015-01-01') + 1, 1)
WEEKDAY('2015-12-31') and WEEKDAY('2015-01-01') are computing the day of the week for the start and end of the year, with 0 = Monday and 6 = Sunday. For the year 2015, these are both 6 (Sunday). So the middle argument of MID is 7 * 6 + 6 + 1, or 49.
The 49th character of the long string is 0. So this means it will add zero to the rest of the expression.
The purpose of this expression is to adjust the weekday count according to what days of the week the first and last day of the year are. In 2015, neither one is a weekday, so it adds zero. Now consider 2016. Jan 1 2016 is a Monday (weekday=1) and Dec 31 2016 is a Tuesday (weekday=2). 7*1+2+1 equals 10. The tenth character of the long string is 1. So it will add one weekday ... intuitively we can see this happens because 2016 is a leap year, so there's one more day in the year. And so on. For each possible beginning and ending day of the year, the long string encodes an adjustment of how many weekdays to add. I imagine that the string was discovered by trial and error.

Group by hour showing breakdown for each day within date range MYSQL

I'm trying to create a query to show the breakdown of leads relating to finance contracts grouped by hour.
Here's an example of what I have so far for hours:
SELECT CONCAT(HOUR(received), ':00-', HOUR(received)+1, ':00') AS Hours,
COUNT(*) as `leads`
FROM (digital_lead)
WHERE `received` BETWEEN '2014-11-01 00:00:00' AND '2014-11-24 00:00:00'
GROUP BY HOUR(received)
And here's the result ....
Hours usage
0:00-1:00 36
1:00-2:00 25
2:00-3:00 16
3:00-4:00 4
4:00-5:00 7
5:00-6:00 8
6:00-7:00 13 // etc all the way to 23:00 - 24:00
OK - so that seems to work, however, it aggregates all of the leads for that time slot over the course of the period set in the BETWEEN statement. I would like to be able to show the breakdown per hour for each day within the period range.
So that would look something like:
Date Hours leads
2014-11-01
0:00-1:00 36
1:00-2:00 25
2:00-3:00 16
3:00-4:00 4
4:00-5:00 7
5:00-6:00 8
6:00-7:00 13 // etc all the way to 23:00 - 24:00
So each date would be displayed and then the hours for that day and so forth.
Thanks.
Group by date as well:
SELECT DATE(received), HOUR(received), ...
...
GROUP BY DATE(received), HOUR(received)
Since you're grouping by hour() only, you'll essentialy be getting
Hour
1 sum of leads in hour 1 of jan 1, jan 2, jan 3, ... dec 31
2 sum of leads in hour 2 of jan 1, jan 2, jan 3, ... dec 31
Rather than
Jan 1 Hour 1 sum of leads for just that one hour on the one day
Jan 1 Hour 2 sum of leads for just that one hour on the one day
..
Dec 31 Hour 23 sum of leads

MySQL query results with weekday between 2 dates

I need a query to get results from a table that has 2 columns
Column startdt (datetime), Column enddt (datetime)
there are some records with startdt 2013-07-19 and enddt 2013-07-29
I need to get the records with weekday = 1 (Tuesday)
the record with date 2013-07-19 is weekday 4 and ends 2013-07-29 which is 0
Actually i want to get the results that has for weekday Monday or another weekday.
You can check the above link for an example
http://sqlfiddle.com/#!2/a80ce/1
If you don't understand what i want to do let me explain. I have an event that starts July 15 and ends July 25. (Starts Monday and ends Thursday) The user selects one of the week days (Monday, Tuesday etc). If he select Tuesday then i want the query that will get all events that are active in Tuesday.
I already found the answer so if anyone want to check it
SELECT articleid,startdt,enddt,dayofweek(startdt), DATEDIFF(enddt,startdt) datedf
FROM events
WHERE (dayofweek(events.startdt) <= 3 AND dayofweek(events.enddt) >= 3)
OR DATEDIFF(enddt,startdt) >=6
(3 is the number of the weekday "Tuesday")
How about using the comments that other people gave you and use a query that combines both dayofweek and a simple greater/smaller/equal syntax as follows:
SELECT * FROM events where dayofweek(events.startdt) <= 6 AND dayofweek(events.enddt) >= 6
This gives the following results if the user specified a friday (= 6):
ARTICLEID STARTDT ENDDT
4 July, 12 2013 00:00:00+0000 July, 26 2013 00:00:00+0000
6 July, 16 2013 00:00:00+0000 July, 20 2013 00:00:00+0000
I do think that you are better of using dayofmonth however as this (maybe just to me) makes it clearer, possibly combining the use of both to ensure that it's active on a friday.
The OP indicates that events which are in the history should also be retrieved and as such the following query does what he wants:
SELECT * FROM events where dayofweek(events.startdt) <= 6 AND dayofweek(events.enddt) >= 6 OR DATEDIFF(enddt,startdt) >=6
How about this solution:
first you convert the day of week in format that 6 is Saturday and 7 is sunday(it's easier for me)
if(dayofweek(o.start_date) = 1, 7, dayofweek(o.start_date) -1)
after that you calc the days from the start_date needed to reach some of the weekdays
(7 - if(dayofweek(o.start_date) = 1, 7, dayofweek(o.start_date) -1)
finally you make sure that the difference in days between the two dates is no less that the above calculation
(7 - if(dayofweek(o.start_date) = 1, 7, dayofweek(o.start_date) -1) <= datediff(o.end_date, o.start_date)