MYSQL ordering by date (string) - php

I have a date column which is formatted like this: 28-15.
The format for this is the first number tells which week, and the second one which year.
I have tried using str_to_date(datecolumn, '%v-%y') with no good results.
It orders the list BUT its not in the correct order.
I also tried concatting the datecolumn to make the string appear like this:
01-28-15 (First is the day of the week) and using str_to_date(datecolumn, '%w-%v-%y), with no luck.
What am I doing wrong?

From MySql docs:
You cannot use format "%X%V" to convert a year-week string to a date
because the combination of a year and week does not uniquely identify
a year and month if the week crosses a month boundary. To convert a
year-week to a date, you should also specify the weekday:
SELECT STR_TO_DATE('200442 Monday', '%X%V %W');
For you case, you need to make assumptions about week day(for example monday) and century(for example 2000), then you can get date next way:
SELECT DATE_ADD(STR_TO_DATE(CONCAT(datecolumn, ' ', 'Monday'), '%V-%X %W'), INTERVAL 2000 YEAR)

Related

Comparing two dates in different month return nothing in PHP

I have a code that looks like this:
while ($DateNow <= $DateFinish) {
echo "<td>".$DateNow." | ".$DateFinish."</td>";
$DateNow = date("d-m-Y", strtotime("next day, ".$Datenow));
}
This code is inside a table so it will make a new cell for every day in a week.
$DateNow start in this week monday, $DateFinish in Saturday. So it will make 6 new <td>.
It works well but the problem occur when the compared date is in different month, like for example Monday 29 Aug with Saturday 3 Sept, it returns nothing. I tried with every possible weeks that has 2 months in it, nothing show up. But when still in 1 month, it shows up.
Any thoughts about this?
When you order a set of dates in d-m-Y format lexicographically (alphabetically), you do not get the ordering you would expect.
For instance
30-01-2016
31-01-2016
01-02-2016
02-02-2016
28-02-2016
29-02-2016
01-03-2016
02-03-2016
becomes
01-02-2016
01-03-2016
02-02-2016
02-03-2016
28-02-2016
29-02-2016
30-01-2016
31-01-2016
after sorting.
To get a more sensible ordering when comparing in this way, you need to change the date format into something more conducive to natural ordering (such as Y-m-d).

MySQL WHERE date smaller than Y-m

Evrey row in my table has a date Y-m-d. Now I want to select only those rows that have a date from before a certain month and year independet of the day. So for example I want all rows with a date befor january 2014.
How would I do this in MySQL? Only considering the month does not work, because it will give me also rows with a month smaller, but a year after my year. E.g. i want rows with date smaller than 03/2013. It will give me also 02/2014.
Of course I could in php define first the first day of the month and than compare the full date. But this does no seem too great and when I want to compare dates after a certain month I have to know how many days a month has.
You can use the STR_TO_DATE function to convert to actual DATE type and then do a simple comparison to the cut-off date.
SELECT *
FROM Your_Table
WHERE STR_TO_DATE(Your_Date_Column,'%Y-%m-%d') < STR_TO_DATE('2013-03-01','%Y-%m-%d');

How to define the relative time for a repetitive yearly interval?

I'm looking for a way to filter for events that happened between previous September (1st) and upcoming September (1st) every year. Since the filter is already part of an existing piece of code I can ony add a fixed date (timestamp) or use a relative date that runs through php strtotime. I can't run any php in the field.
Because a timestamp is fixed for a set year, I want to use relative dates to make this filter work every year.
I have tried to build this filter using simple things like [last/next] September, but that is invalid strtotime syntax.
From there I tried things like 9/1 [last/this/next] year. They were valid, but since I can't use logic to determine which one to use, it is not good.
For dates prior to this year September 1st the filter would be 9/1
last year>9/1 this year
For dates past September 1st this year it is 9/1 this year>9/1 next year.
So to summarize, I am looking for a relative date string (strtotime) to get the previous September 1st and a string for the upcoming September first. (If they exist.)
i guess you want dates in between 2012/09/01 - 2013/09/01.
you can use string in link if that's what your talking about, but you need years.
$this_year='2013/09/01';
$last_year = date("Y-m-d",strtotime("$this_year - 1 year"));
$next_year = date("Y-m-d",strtotime("$this_year + 1 year"));
echo
" last year
this year
next year
";
if(strtotime($this_year) <= strtotime($filter_date) and strtotime($filter_date) >= strtotime($last_year))
{
// dates in between 2012/09/01 - 2013/09/01
}
if(strtotime($this_year) >= strtotime($filter_date) and strtotime($filter_date) <= strtotime($next_year))
{
// dates in between 2013/09/01 - 2014/09/01
}
if you are getting data from database then use code below as its easier.
SELECT * FROM table_name WHERE 'date_field' BETWEEN ('$this_year') and ('$last_year ')

select data by date range with year wrapping

I dont know if this is even possible. I have a MySQL table containing season start and end dates for advertisers. The dates dont change from year to year so they are stored in MM-DD format.
These are normally consective within a year , ie March 1st (03-01) to October 1st. (10-01).
BUT the seasons may wrap around a year end, eg October 1st. (10-01) to March 1st (03-01) (ie they are closed in the spring & summer)
Now I need to select entries (via PHP) where a date range entered by a user ( say December 1st to December 12th.) falls within advertiser season start/end dates.
Easy enough if the season start/end were mathematically consecutive ( eg 03-01 - 10-01) but how do I do it when they may or may not be consecutive.
Sorry if I havent explained that clearly but my head's about to explode....
Use the proper column type (DATE) for this data, and the season wrapping becomes a non-issue.
To get the season(s) that the user-supplied date range applies to:
SELECT foo
FROM seasons_table
WHERE <user range low> >= season_range_low
AND <user range high> <= season_range_high
How about:
SELECT *
FROM table
WHERE CASE
WHEN date_start > date_end THEN
$date_to_check >= date_start OR $date_to_check <= date_end
ELSE
$date_to_check >= date_start AND $date_to_check <= date_end
END;
you should be able to use an AND statement in your SQL to check for the two possibilities:
SELECT * FROM table WHERE
season_start_date <= advertiser_start_date AND
season_end_date >= advertiser_end_date OR
No matter what the season end date needs to be a higher value than the ad end date, even if it's in the new year. So that should work, but I agree with #SoboLAN, it would be much simpler if you just add the year to the date fields.

MySQL: Calculate the difference between Date/Times - only during M-F "Work week"

I need to calculate a difference between a starting date/time and an ending date/time. But, I only want to do this for the 5-day work week (exclude Sat/Sun as days). What is the best way to do this? My thought is that from the date, I'll have to get the day of the week and if it is a weekday, then I add to the accumulator. If it's not, then I don't add anything.
I'm sure someone has done this before, but I couldn't seem to find anything searching. Any links or other help would be very useful.
Many thanks,
Bruce
DAYOFWEEK returns 1 for Sunday and 7 for Saturday. I'm not sure how your schema is set up, but this will perform a TIMEDIFF of two dates that are on a Monday - Friday work week.
select TIMEDIFF(date1,date2) from table
where DAYOFWEEK(date1) not in (1,7) and DAYOFWEEK(date2) not in (1,7)
MySQL DATE/TIME functions
EDIT: From Bruce's comment about holidays. If you have a table full of holiday dates, something like this would work to exclude processing those days:
select TIMEDIFF(date1,date2) from table
where date1 not in (select holiday from holiday_table) and
date2 not in (select holiday from holiday_table) and
DAYOFWEEK(date1) not in (1,7) and DAYOFWEEK(date2) not in (1,7)
NETWORKDAYS() "Returns the number of whole working days between start_date and end_date. Working days exclude weekends and any dates identified in holidays. Use NETWORKDAYS to calculate employee benefits that accrue based on the number of days worked during a specific term." according to the Excel 2007 help file.
The "between" description is a bit inaccurate because it includes the start and end dates, i.e. networkdays(21-01-2010. 22-01-2010) = 2. It also takes no account of times.
Here's a function in PHP that will give the same results. It doesn't work properly if the end date is less than the start date, nor does do anything about holidays (see below the function).
function networkdays($startdate, $enddate)
{
$start_array = getdate(strtotime($startdate));
$end_array = getdate(strtotime($enddate));
// Make appropriate Sundays
$start_sunday = mktime(0, 0, 0, $start_array[mon], $start_array[mday]+(7-$start_array[wday]),$start_array[year]);
$end_sunday = mktime(0, 0, 0, $end_array[mon], $end_array[mday]- $end_array[wday],$end_array[year]);
// Calculate days in the whole weeks
$week_diff = $end_sunday - $start_sunday;
$number_of_weeks = round($week_diff /604800); // 60 seconds * 60 minutes * 24 hours * 7 days = 1 week in seconds
$days_in_whole_weeks = $number_of_weeks * 5;
//Calculate extra days at start and end
//[wday] is 0 (Sunday) to 7 (Saturday)
$days_at_start = 6 - $start_array[wday];
$days_at_end = $end_array[wday];
$total_days = $days_in_whole_weeks + $days_at_start + $days_at_end;
return $total_days;
}
To take holidays into account, you'd have to work out the number of days using this function, then use a query like
Select count (holiday_date) from holidays
where holiday_date between start_date and end_date
and DAYOFWEEK(holiday_date) not in (1,7)
Be careful that there isn't a problem with the end_date being treated as 00:00 (i.e. first thing in the morning) - you may have to condition it to be 23:59:59 so that it works properly. It all depends on how your holidays are stored.
To return the holidays in the same time period and subtract that from the number you first thought of.

Categories