Issue with dates in Informix DB 11.70 - date

I'm using informix DB 11.70, and this issue is ticking me off pretty badly.
When I insert a client into my DB, no matter what date I input, when I fetch back the date it brings some random date in 1894.
What issue could it be? It throws no errors when I send entries, no 'Invalid month in date' nonsense.
Pls help.

The "epoch date" for Informix is 01-01-1900. In other words, date ZERO = "12-31-1899", date 1 = "01-01-1900", date 2 = "01-02-1900", today ("09-24-2013") is stored numerically as 41540.
I think either your client application is being too clever by half, or you aren't putting quotes around your dates, and either way the server is treating your dates as numeric calculations.
In other words, you enter something like 05-11-2010, and your client sends that to the database as 5 minus 11 minus 2010, or -2016. Day number -2016 is "06/24/1894".
I bet if you enter your dates with a slash rather than a dash (i.e. "09/24/2013"), you'll always get 9 divided by 24 divided by 2013 = close to zero => "12/31/1899".
You haven't said if you're using plain old SQL via DB-Access, or ODBC, or something else. But I'll guarantee your dates are not being enclosed in quotes, and are therefore getting treated as arithmetic expressions.

Related

Data stored as DD/MM/YYYY in table, but querying in DD/MM/YYYY doesn't work for all dates MS Access 2016

There are probably many questions that are asking about date formats, but I haven't found anything like this.
I have a table, called t_birthday. t_birthday has a field called "DayOfMonth" which currently stores the data in a dd/mm/yyyy format. Lets say the record I have has the Date of 01/12/2016 (Dec 1, 2016).
Now, if I create a query using the "Query Design" option in the Create tab, I select my table t_birthday. For the field option, I select DayOfMonth. In the criteria option, I put =#01/12/2016#. When I click Run, it queries the database and returns the record with that date successfully.
However.. If I check the SQL generated from this Query Design, it is this:
SELECT t_birthday.DayOfMonth
FROM t_birthday
WHERE (((t_birthday.DayOfMonth)=#12/1/2016#));
If I try copy and pasting the DayOfMonth value from the table into that query, it wouldn't work. Notice how the format in the query is mm/dd/yyyy, but in my table it's still dd/mm/yyyy. I never touched any of the date formatting options in my table, or even on my computer. When I actually create this record using a form, I have a date picker which is in the form of dd/mm/yyyy as well.
Questions:
In the query design, when I specify criteria in dd/mm/yyyy, why does it generate sql in the form of mm/dd/yyyy?
I can only query dates using dd/mm/yyyy format if the day number (1-31) is 13 or above, OR if the month value and the day value are the same (October 17, Jan 1, March 3, November 11, December 12, etc). mm/dd/yyyy still works for those dates previously mentioned. I can't query dates like November 7th, Feb 3rd, August 4th, etc using dd/mm/yyyy though. How do I get around this problem? I store the dates, and I use the values directly from the table as conditionals in my queries. I shouldn't have to alter my date value in order to use them.
Why can I write an SQL statement for dates with the day number above 13 in dd/mm/yyyy format or mm/dd/yyyy format? E.g., the WHERE clause can look like: WHERE DayOfMonth=#13/06/2018 or WHERE DayOfMonth=#06/13/2018 and it still returns the same record? Why does access not enforce a specific format?
EDIT:
Currently I run my query in VBA and return it into a recordset using the following:
Dim bdayRecords As RecordSet
Dim sql As String
sql = "SELECT t_birthday.DayOfMonth"
sql = sql & " FROM t_birthday"
sql = sql & " WHERE (((t_birthday.DayOfMonth)=#" & rs("DayOfMonth") & "#));"
bdayRecords = CurrentDb.OpenRecordset(sql)
Where rs in the where clause was a previous recordset with a date value stored in "DayOfMonth". The rs recordset retrieved the date value from a different table in the exact same way bdayRecords was populated.
bdayRecords won't find the records with the date values matching the criteria explained before.
Use a properly formatted string expression for the date value retrieved:
sql = sql & " WHERE t_birthday.DayOfMonth = #" & Format(rs("DayOfMonth").Value, "yyyy\/mm\/dd") & "#;"
The ISO sequence yyyy-mm-dd works everywhere, so make it a habit to use that.
SQL always uses mm/dd/yyyy. That's not dependent on how you format it.
You never actually store a date in a certain format. You display a date in a certain format. All dates in Access are stored as a double-precision floating number containing the number of days elapsed since 30-12-1899, with fractions as time. How dates are formatted has no influence whatsoever on your SQL statement
Always use either mm/dd/yyyy or yyyy-mm-dd in your SQL. VBA only takes mm/dd/yyyy.
However, Access is opportunistic when working with clearly invalid dates, such as 13/1/2018. Because no 13th month exists, it parses it as the 13th of january, even though it's not a valid date.
If you're using values from other queries, there shouldn't be any problems, since the values never get cast back and forth to strings. You only get in trouble when casting a date to a string and then back to a date, which is not something you should do in queries, ever.
To avoid casting back and forth between strings, you can either refactor your code to a single query instead of retrieving a value from a recordset and inserting that value in a string SQL statement, or use parameters, which allows you to use the date value directly in an SQL statement.
For explanations why these design choices are made, ask Microsoft, they wrote the program. This is just how it works.

Enforce the user to enter a year

I have an application form, where i placed text item where the user enter manually a year like for example: 2016.
I tried to enforce the user to enter correctly the year on its format, not for example charcters or numbers.
Any way to that?
Thanks everyone!
Can you update the form yearly and if so to make it work universally you could just convert to an int and check if intYear = currYear. I mean there are a lot of other fixes including if Year>= 2016- then allow which could still get you things like 9999 but then you could do a opposite. Although ultimately the most efficient would be getting the computers year which may propose challenges but would work for more year and only have problem with people who have incorrect year.
The year should be entered as a number. You can verify that it is an integer, that it is <= current year, and >= 1993 (for example), like this:
... yr = round(yr) and yr between 1993 and extract (year from sysdate)
Honestly, I am not familiar with Oracle forms; this may be a check, for example, in an "if ... then ... else" structure in a stored procedure, and raise an error if the condition is not met. yr is the name of the input variable. If the user enters '2015' (with the single quotes) instead of 2015 (as a number) Oracle will likely convert it to a number, silently and without warning, and it will pass the test - but then you can safely assume the user really meant to enter 2015; no harm will result.

What does a negative integer Date value mean in MongoDB?

I've discovered an issue with some of data being stored in MongoDB. We have a field that stores a Date, and normally this includes values like ISODate("1992-08-30T00:00:00.000Z") or ISODate("1963-08-15T00:00:00.000Z"). That's nice and straight-forward; I can easily look at those dates and see August 30, 1992 or August 15, 1963.
However, I've noticed a couple of entries where the date looks something like this instead:
Date(-61712668800000)
I'm honestly not sure how the data got persisted that way in the first place, as it should have been stored the former way. And I'll have to address the software bug with my code that is intermittently causing it to be stored that way.
However, the bigger problem is what to do with data entries that look like that. I'm not even sure what date that was supposed to be. My first assumption is that it's just milliseconds, like a UNIX timestamp or something, but that's not right. Even if I flip the negative sign and remove some of the trailing zeros, that still ends up being a date way in the future (e.g. July 23, 2165), and that's not correct. It should be a date in the past.
And the other big problem is that I'm not sure how to even search for this in the database. I can't utilize a $type query because the type is still 9 (i.e. it still thinks it's a "Date").
Has anyone else encountered these weird date entries before? How can I find them? And how can I recover the actual date from them?
The problem seems to be that your code is storing dates prior to the epoch, which are furthermore so far into the past that they cannot be represented using an ISODate wrapper:
As per the documentation
(emphasis added)
Date
BSON Date is a 64-bit integer that represents the number of
milliseconds since the Unix epoch (Jan 1, 1970). This results in a
representable date range of about 290 million years into the past and
future.
The official BSON specification refers to the BSON Date type as the
UTC datetime.
Changed in version 2.0: BSON Date type is signed. [2] Negative values
represent dates before 1970.
Although not explicitly stated in the Mongo documentation, it appears that they are following a strict interpretation of the ISO 8601 standard and not one of the variants which are allowed "by trading partner agreement" based on what I found at wikipedia
Years
YYYY ±YYYYY ISO 8601 prescribes, as a minimum, a
four-digit year [YYYY] to avoid the year 2000 problem. It therefore
represents years from 0000 to 9999, year 0000 being equal to 1 BC and
all others AD. However, years prior to 1583 are not automatically
allowed by the standard. Instead "values in the range [0000] through
[1582] shall only be used by mutual agreement of the partners in
information interchange."[9]
To represent years before 0000 or after 9999, the standard also
permits the expansion of the year representation but only by prior
agreement between the sender and the receiver.[10] An expanded year
representation [±YYYYY] must have an agreed-upon number of extra year
digits beyond the four-digit minimum, and it must be prefixed with a +
or − sign[11] instead of the more common AD or BC (or the less widely
used BCE/CE) notation; by convention 1 BC is labelled +0000, 2 BC is
labeled -0001, and so on.[12]
If you read through the rest of the article you will also see that the reason the number of digits must be pre-defined is so that the date can be stored unambiguously without using separator characters such as "-" between the components.

SAS - Create a month and year date from one integer

I have a data set in which month and year are in one variable and come in the form 200801 which equates to 2008, January. How can I create a SAS date from this integer?
I would like something in the form of Jan 2008 - anything so that SAS recognizes it as a date, as I then need to subtract this value from service date to find out how much time has elapsed since enrollment into the dataset until date of service.
Please also keep in mind that this is a variable, and I have thousands of observations. So I also need the data step/ function to do this for the entire variable.
Any help is appreciated!
You need to put it to a character variable, then input back to numeric. You can do that pretty easily.
date_var = input(put(date_var_orig,6.)||'01',yymmdd8.);
You can also do it this way:
date_var = mdy(mod(date_var_orig,100),1,floor(date_var_orig/100));
Both assume you want the day to equal 1; make a choice there if you want something else (like end of month or middle of month).

UniVerse native date format

I am in the process of optimizing some UniVerse data access code we have which uses UniObjects. After some experimentation, it seems that using a UniSession.OConv call to parse certain things such as decimal numbers (most we have a MR4 or MR2 or MR2$) and dates (almost all are D2/) is extremely slow (I think it might make a call back to the server to parse it).
I have already built a parser for the MR*[$] codes, but I was wondering about the dates as they are stored so I can build one for D2/. Usually they seem to be stored as a 5 digit number. I thought it could be number of days since the Unix Epoch since our UniVerse server runs on HP-UX, but after finding '15766' as a last modified date and multiplying it by 86400 (seconds per day), I got March 02, 2013 which doesn't make sense as a last modified date since as far as I know that is still in the future.
Does anyone know what the time base of these date numbers are?
It is stored as a number of days. Just do a conversion on 0 and you will get the start date.
Edit:
As noted by Los, the Epoch used in UniVerse (and UniData) is 31st Dec 1967.
In Universe and any other Pick database, Dates and Times are stored as separate values.
The internal date is the number of days before of after 31/12/1967, which is day zero.
The internal time is the number of seconds after midnight. It can be stored as a decimal but is not normally.
In TCL there is a CDT command (stands for Convert Date) that converts dates from human readable to numeric and and vice versa:
CDT 9/28/2017
* Result: 18169
CDT 18169
* Result: 09/28/2017