As has already been mentioned, The Format() function turns a date into a STRING from which point forward, it will act like a string rather than a date. That means that 01/01/2019 will be LESS THAN 12/31/2018. I have several apps that work both in the US and in the UK and they work because I NEVER format dates EXCEPT when I have to build SQL Strings in VBA. I rely on the local date settings in all other cases. I always use "short date" as the format property for unbound date fields and only use specific date formats when I need to reduce space or for some other reason only want to show part of a date.
Formatting is for human consumption and Format() should only be used when you actually want to return a string that LOOKS LIKE a date as when you are creating embedded SQL strings since SQL requires that string dates be in mm/dd/yyyy format.
For your forms and reports, as long as you are using bound contols, Access will know which controls are dates and will format them based on your default Windows settings so there is no need to specifically set the Format property on controls unless the control is unbound. So if you are using a form and the user enters a start and end date into an unbound control with its Format PROPERTY set to Short Date (never be specific unless you have to because you are only showing a partial date)
In a querydef, you would use
Select ... From ... Where SomeDate Between Forms!yourform!startDate and Forms!yourform!EndDate
However, in an SQL STRING built with VBA, you would use
strSQL = "Select ... From ... Where SomeDate Between #" & Me.StartDate & "# AND #" & Me.EndDate & "#"
When you want to do something with a date ALWAYS use date functions, never try to pull out parts using Left(), Right(), and Mid() functions. DateSerial is the best way to substitute a date part. Minty gave you a link in #6.
If you use the suggested DateSerial() you end up with a date rather than a string so you would not need to use cDate(). Your expression should be:
IIf(DateSerial(Year(Date()), Month(MyDate), Day(MyDate)) <= Date(), DateAdd("yyyy", 1, DateSerial(Year(Date()), Month(MyDate), Day(MyDate)), DateSerial(Year(Date()), Month(MyDate), Day(MyDate)))
This expression works entirely with dates. No strings are produced. That means it works regardless of what your Windows date format is set to. It differs from your results in one way.
1. Now() = today's date and TIME. That means that today's date will ALWAYS be less than Now() because the date expression has no time component. I changed the relational operator to be <= to compensate. If your business rule is that you want to know if the date is actually less than today, then just use the < as you did originally but with the correct date function.
To summarize.
1. Date() = today's date and Now() = today's date + time of day -- they are DIFFERENT values so make sure you use the correct function.
2. Formatting dates turns them into strings so just don't do it unless you actually want a string. If you want a date to operate like a date, use the proper date function.