Date Comparison - Condition fails, but returns True - ms-access

I am trying to compare a date against the first of next month from last year. If the date from date1 is less than the first of next month from last year then I want it to return true. The condition only seems to fail if I set the date to one year ahead.
LastRightToKnow = 7/14/2011
Dim RTK As String
RTK = ""
If [NeedsRightToKnow] = -1 And [LastRightToKnow] < DateSerial(Year(Now() - 1), Month(Now() + 1), 1) Then
RTK = "Right-To-Know"
End If
So, from my understanding, I gather that if today = 6/14/2012 then
DateSerial(Year(Now() - 1), Month(Now() + 1), 1) = 7/01/2011
LastRightToKnow = 7/14/2011
therefore 7/14/2011 < 7/01/2011 should return False. However it returns true... What am I missing?

Your formula is off because of the placement of the parethesis:
? DateSerial(Year(Now() - 1), Month(Now() + 1), 1)
6/1/2012
? DateSerial(Year(Now()) - 1, Month(Now()) + 1, 1)
7/1/2011
Edit: need to do the same for month

Now() +1 = tomorrow
I think you mean
DateSerial(Year(Now())-1, Month(Now())-1, 1) = 7/01/2011

Related

How can I update an interval of dates in the database (Hibernate HQL)

Consider, for some specific database entry of id id, an interval of dates in the database, from BEGIN_DATE to END_DATE, denoted by (BEGIN_DATE,END_DATE).
Given two new dates, that form the interval (newBeginDate, newEndDate), I must update (BEGIN_DATE,END_DATE) so that the resulting interval contains all 4 dates. In other words, I want to add the two intervals (And since I am adding them, the resulting interval may remain the same or grow, but never shrink).
A few examples:
If (BEGIN_DATE,END_DATE) = (January 10,January 20), then:
(BEGIN_DATE,END_DATE) + (Jan 15,Jan 25) = (Jan 10,Jan 25)
(BEGIN_DATE,END_DATE) + (Jan 05,Jan 15) = (Jan 05,Jan 20)
(BEGIN_DATE,END_DATE) + (Jan 05,Jan 25) = (Jan 05,Jan 25)
(BEGIN_DATE,END_DATE) + (Jan 15,Jan 15) = (Jan 10,Jan 20)
(BEGIN_DATE,END_DATE) + (Jan 10,Jan 13) = (Jan 10,Jan 20)
The two following queries together achieve this goal. The first one updates BEGIN_DATE, and the second updates END_DATE:
session.createQuery(
"update APPOINTMENTS " +
"set BEGIN_DATE = :newBeginDate " +
"where " +
"(BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) " +
"and ID = :id ")
.setParameter("newBeginDate", newBeginDate)
.setParameter("id", id)
.executeUpdate();
session.createQuery(
"update APPOINTMENTS " +
"set END_DATE = :newEndDate " +
"where " +
"(END_DATE is null or END_DATE < :newEndDate) " +
"and ID = :id ")
.setParameter("newEndDate", newEndDate)
.setParameter("id", id)
.executeUpdate();
My question is:
How can I do it in a single query?
SQL is limited when it comes to more complex programming constructs, so since you use Hibernate I would just read the appointment entity instance and update its fields. That would require two queries, one to read and one to update, but still it would be only one update statement and is the most readable solution.
If you still want only one update statement and nothing else, your two statements could be merged into one by using case:
update APPOINTMENTS
set BEGIN_DATE = case when (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) then :newBeginDate else BEGIN_DATE end,
END_DATE = case when (END_DATE is null or END_DATE < :newEndDate) then :newEndDate else END_DATE end
where (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate or END_DATE is null or END_DATE < :newEndDate)
and ID = :id
Use LEAST() and GREATEST() functions. For NULLs use COALESCE().
update APPOINTMENTS
set BEGIN_DATE = coalesce(least(BEGIN_DATE, :newBeginDate), :newBeginDate),
END_DATE = coalesce(greatest(END_DATE, :newEndDate), :newEndDate)
where ID = :id
I think LEAST and GREATEST don't need an explanation. COALESCE will pick the new date, if the old one is NULL. So no condition except of ID = :id is needed in the WHERE clause.

Add Character on date in SQL Server

If today's date is greater than 10, then it will show like this:
Today = 20170611
Result = 20170710M1231
I tried this
CASE
WHEN (SUBSTRING(CONVERT(VARCHAR(6), GETDATE(), 112), 4, 2)) > 10
THEN (DATEADD(MONTH, 1, (SUBSTRING(CONVERT(VARCHAR(6), GETDATE(), 112), 1, 6)))) + '10M1231'
ELSE ''
END AS FREQUENCY
but I couldn't get the desired answer
You were adding the month after spliting the date,this should work
SELECT CASE WHEN DAY(GETDATE()) > 10
THEN (SUBSTRING(CONVERT(VARCHAR(6),DATEADD(MONTH,1,GETDATE()),112),1,6))+'10M1231'
ELSE '' END AS FREQUENCY

Set Date Format in Variable

Just wondering if anyone can help me setting a date variable for a report to run between certain dates every year without needing to be updated manually.
For example, I have the dates hard-coded below, but I was wondering if I could set a date format for when it goes into 2017 that the dates will change for the 2017 year. I presume there is a way to set a yearly date format I am just not sure how.
This is my hard-coded variables I set.
Put in the wrong Date Ranges changed as below.
set #start_date = '2016-01-02';
set #end_date = '2017-01-01';
Below is what I have in my where clause also.
and create_date between #start_date and #end_date
Your range covers all days in the year, except January 1. So you can simply check the day and month:
WHERE NOT (DAY(create_date) = 1 AND MONTH(create_date) = 1)
set #start_date = CAST(CAST(YEAR(getdate()) AS nvarchar(4)) + '0102' AS DATETIME);
to get end of current year
SET #end_date = DATEADD(day, -1 , DATEADD(month,13 - MONTH(getdate()), DATEADD(day,1 - DAY(getdate()),getdate())));
I assume you want the FULL "current year" based on "today"
MySQL
select *
from whatever
where ( create_date >= CONCAT(YEAR(CURDATE()),'-01-01')
and create_date < CONCAT(YEAR(CURDATE())+1,'-01-01')
)
Test it with:
SELECT
CONCAT(YEAR(CURDATE()),'-01-01') This_year_start
, CONCAT(YEAR(CURDATE())+1,'-01-01') Next_year_start
SQL Server (tsql)
select *
from whatever
where ( create_date >= DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)
and create_date < DATEADD(YEAR, DATEDIFF(YEAR, -1, GETDATE()), 0)
)
Test it with:
select
DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()) , 0) This_year_start
, DATEADD(YEAR, DATEDIFF(YEAR, -1, GETDATE()), 0) Next_year_start
This_year_start Next_year_start
01.01.2016 00:00:00 01.01.2017 00:00:00
DATEDIFF(YEAR, 0, GETDATE()) calculates the number of years from the
base year
add that number of years to the base date (1900-01-01)
DATEDIFF(YEAR, -1, GETDATE()) calculates the number of years from
year before the base year (is a bigger number, by 1, than above)
add that number of years to the base date (1900-01-01)
Please avoid using between for date ranges. It is far safer to use a combination of >= and <
e.g.
where create_date >= '2016-01-01' and create_date < '2017-01-01'
With that approach, no matter what time precsion applies to the data in [create_date] you will get the precise range of information requested.
Here you go.
declare #s datetime, #e datetime
set #s=cast(cast(year(getdate()) as char(4))+'-01-02' as date)
set #e=cast(cast(year(getdate()) as char(4))+'-12-31' as date)
select #s,#e

MS Access get ISO standard week number

I'm surprised that I can't find any existing solutions to this online but I just need an SQL function that returns an ISO standard week number (i.e. the start of week 1 is always the first Monday of the year).
None of the DatePart function options consistently return the correct result. I had thought the option "vbFirstFourDays - Start with the first week that has at least four days in the new year." but testing it for today (12th Jan) returns week 3, not week 2 (my expression is DatePart("ww",Now(),2) )
This year ISO week 1 starts on 4th Jan, next Year the 2nd Jan and last year it was the 5th of Jan.
Many thanks
The DatePart function does indeed calculate the ISO-8601 week number almost* correctly when it uses vbMonday for the firstdayofweek argument and vbFirstFourDays for the firstweekofyear argument, e.g.,
DatePart("ww", Date(), vbMonday, vbFirstFourDays)
or, when used directly in an Access query
DatePart("ww", Date(), 2, 2)
* Note that the bug documented here has apparently never been fixed, so the following Mondays in the 21st century are reported as being in week 53 when according to ISO-8601 they should be in week 1 of the following year:
2003-12-29
2007-12-31
2019-12-30
2031-12-29
2035-12-31
2047-12-30
2059-12-29
2063-12-31
2075-12-30
2087-12-29
2091-12-31
Just to follow on from Gord Thompson, Microsoft have provided a workaround which returns the correct ISO week in all circumstances. It simply changes week 53 to week 1. Simply place this in a VBA Module and then you'll be able to use the function in Excel/Access.
Public Function ISOWeek(MyDate As Date) As Integer
ISOWeek = Format(MyDate, "ww", vbMonday, vbFirstFourDays)
If ISOWeek > 52 Then
If Format(MyDate + 7, "ww", vbMonday, vbFirstFourDays) = 2 Then ISOWeek = 1
End If
End Function
There are more problems with the ISO weeknumbers than just the 2 week digits returned by DatePart.
January 1st on a Friday should be in week 53 of the previous year
December 31 on a Monday should be in week 1 of the next year
A lot of businesses in Europe use a four digit number to show year and week together. In those cases:
Friday #01/01/2021# should be shown as week "2153"
Monday #12/31/2018# should be shown as week "1901"
I have created 2 wrappers around the DatePart function to add the correct year and show the right weeknumber in case DatePart is in error.
Public Function ISO_YYWW(dat As Date) As String ' ISO 8601 / NEN 2772
Dim ww As Integer
ww = CInt(ISO_WW(dat))
If ww >= 52 And Val(Format(dat, "ww")) <= 2 Then
ISO_YYWW = Format(((Year(dat) - 1) Mod 100), "00") & Format(ww, "00")
ElseIf ww = 1 And Month(dat) = 12 Then
ISO_YYWW = Format(((Year(dat) + 1) Mod 100), "00") & Format(ww, "00")
Else
ISO_YYWW = Format(dat, "YY") & Format(ww, "00")
End If
End Function
Public Function ISO_WW(dat As Date) As String ' ISO 8601 / NEN 2772
If Format(dat, "DD-MM") = "31-12" And DatePart("W", dat, vbMonday, vbFirstFourDays) = 1 Then ' 31-dec on a monday
ISO_WW = "01"
ElseIf Format(dat, "DD-MM") = "30-12" And DatePart("W", dat, vbMonday, vbFirstFourDays) = 1 Then ' 30-dec on a monday
ISO_WW = "01"
ElseIf Format(dat, "DD-MM") = "29-12" And DatePart("W", dat, vbMonday, vbFirstFourDays) = 1 Then ' 29-dec on a monday
ISO_WW = "01"
Else
ISO_WW = Format(DatePart("ww", dat, 2, 2), "00")
End If
End Function
I have tested from 1970 to 2021 and found no problems using this code
Sub test()
Dim dat As Date, yy As Integer, f As Integer
f = FreeFile
Open CodeDb.Name & ".txt" For Output As #f
Print #f, "date", "day", "ISO_WW / DOW", "ISO_YYWW"
For yy = 1970 To 2021
For dat = CDate("31/12/" & yy) - 7 To CDate("31/12/" & yy) + 7
If ISO_WW(dat) >= 52 Or ISO_WW(dat) = "53" Or Val(ISO_WW(dat)) = 1 Then
Print #f, Format(dat, "yyyy-mm-dd"), Format(dat, "DDD"), ISO_WW(dat) & " / " & DatePart("W", dat, vbMonday, vbFirstFourDays), ISO_YYWW(dat)
End If
Next dat
Print #f, ""
Next yy
Close #f
End Sub

Date difference in mysql based on 360 days

I working on a financial project where i need to calculate the difference of arrear days. If I use the method datediff() of mysql then it returns the result based on 365 days. I need the result based on 360 days. if use the following sql query
select datediff('20140908','20130908') from dual;
mysql returns the date difference 365. This is the actual date difference but in accounting/Financial calculation the difference is exactly one year (360 days). This is what I want. The result should be 360 instead 365.
Currently I want to use US standard.
to get the same result like Excel, I found the following code to use in MySQL:
select case
when (day(Startdate)>=30 or Startdate=last_day(Startdate) then
case
when(day(Enddate)>=30) then
30*(12*(year(Enddate)-year(Startdate))+month(Enddate)-month(Startdate))
else
30*(12*(year(Enddate)-year(Startdate))+month(Enddate)-month(Startdate))+days(Enddate)-30
end
else
30*(12*(year(Enddate)-year(Startdate))+month(Enddate)-month(Startdate))+days(Enddate)-days(Startdate)
end
Use
TO_DAYS(date2) - To_DAYS(date1)
It returns the number of days between date1 and date2. Then you can do with the result what you need.
sdate = from date
edate = to date
this calculate the days between the 2 date, taking into account that a month is 30 days, 1 year is 360 days, and checking if the date are at the end of the month, so e.g. from 1.1.2019 to 28.2.2019 = 60 days etc.
to be 1 month or 1 year, the edate should be a day before, so 1.1 - 31.1 = 30 days, 1.1 - 1.2 = 31 days
SELECT GREATEST(
0,
(YEAR(DATE_ADD(edate, INTERVAL 1 DAY)) - YEAR(sdate)) * 360 +
(MONTH(DATE_ADD(edate, INTERVAL 1 DAY)) - MONTH(sdate)) * 30 +
(
IF(DAYOFMONTH(DATE_ADD(edate, INTERVAL 1 DAY)) = DAYOFMONTH(LAST_DAY(DATE_ADD(edate, INTERVAL 1 DAY))), 30, DAYOFMONTH(DATE_ADD(edate, INTERVAL 1 DAY))) -
IF(DAYOFMONTH(sdate) = DAYOFMONTH(LAST_DAY(sdate)), 30, DAYOFMONTH(sdate))
)
Pretty late here, but posting my solution for future reference
CREATE FUNCTION `DAYS360_UDF`(sdate DATE, edate DATE)
RETURNS INTEGER
DETERMINISTIC
CONTAINS SQL
BEGIN
DECLARE sdate_360 INTEGER;
DECLARE edate_360 INTEGER;
SET sdate_360 = ( YEAR(sdate) * 360 ) + ( (MONTH(sdate)-1)*30 ) + DAY(sdate);
SET edate_360 = ( YEAR(edate) * 360 ) + ( (MONTH(edate)-1)*30 ) + DAY(edate);
RETURN edate_360 - sdate_360;
END
Usage -
select DAYS360_UDF('20130908', '20140908')