quantlib-python date method seems missing - quantlib

I am trying to run this in quantlib-python:
import QuantLib as ql
date = ql.Date(31, 3, 2015)
date
returning: Date(31,3,2015)
but it is supposed to return: March 31st, 2015
I am new to quantlib-python. What am I missing? Thank you.
I am using VC2015/quantlib 1.8/quantlib-swig-1.8

When you only write date, your interpreter calls the __repr__ method and displays the result. If you say print date, instead, it calls the __str__ method, which is what you're looking for. The two methods have different purposes in Python (see e.g. Purpose of Python's __repr__) and are often implemented differently; you can try the same thing with datetime.date and see what happens.

Related

ParseDateTime won't output ODBC literals for SQL Server datetime queries

After setting up ColdFusion 2021 I found that when ParseDateTime is being used to format a datetime value from SQL Server it won't format the date as an ODBC literal like ColdFusion 2016 does, e.g. {ts '2021-05-15 13:20:51'}. Instead it just outputs the value unchanged from the database.
Here is my environment:
Coldfusion 2016 Server:
Version: 2016,0,17,325979
Tomcat Version: 8.5.61.0
Edition: Developer
Operating System: Windows 7
Coldfusion 2021 Server:
Version: 2021,0,01,325996
Tomcat Version: 9.0.41.0
Edition: Developer
Operating System: Windows 10
The database is SQL Server 2008 R2 and ColdFusion datasource is using the MS SQL Server driver.
An example query:
<cfquery name="qryDates">
select id, expiry_date
from purchases
</cfquery>
<cfoutput>#ParseDateTime(qryDates.expiry_date)#</cfoutput>
Coldfusion 2016 output:
{ts '2021-05-15 13:20:51'}
Coldfusion 2021 output:
2021-05-15 13:20:51.0
Is there a way to get ParseDateTime to behave the way it does on my CF 2016 and every other CF server I have used in the past? I do not want to have to change the formatting to accomplish this (e.g. #DateTimeFormat(ParseDateTime(qryDates.expiry_date))#).
Thank you for any advice.
I don't have any way to test my assumptions right now, but I assume you're seeing the side effects of the way ParseDateTime() handles a Java object, and the differences of that function between CF2016 and CF2021/18.
Since expriry_date is an actual datetime object in your database, cfquery from the database will give you a sql object instead of just a string that looks like a date. Since it has both date and time components, I believe that JDBC will send a java.sql.Timestamp object back to CF.
The purpose of ParseDateTime() is for converting a string to a date object, and even though it can "format" a date object, that's not what it's intended for. It's initial assumption is that it's being given a string, and because CF is dynamically typed, it will usually try to implicitly convert a value into the correct type. And since the database value is date-ish, CF will try to make it appropriately look like a string. At least that's the way it was intended to work. And it looks like that is what is happening in <CF2016 and Lucee, and the value is getting a "{ts...".
It appears that CF2021/18 is receiving a date object and not really doing much with it. It seems to be just passing the Java object (without the "{ts...") back out, and when ColdFusion tries to convert it to a string, it's not a ColdFusion timestamp variable so there is no "{ts...".
DEMO CODE:
<cfscript>
/*** CREATE QUERY OBJECT ***/
theDateQuery = QueryNew("dt","timestamp",[{"dt":createODBCDateTime('2021-04-09 12:01:02.345')}]) ;
writeDump(theDateQuery);
/*** SET QUERY RESULT TO A VARIABLE ***/
dobj = theDateQuery.dt[1] ;
writeOutput("dobj: " & dobj & " ("& getMetadata(dobj).getName() & ")<br>");
/*** CONVERT QUERY VARIABLE TO A STRING ***/
dstr = theDateQuery.dt[1].toString() ;
writeOutput("dstr: " & dstr & " ("& getMetadata(dstr).getName() & ")<br>");
/*** PARSEDATETIME OF OBJECT ***/
x = parseDateTime(dobj) ;
writeOutput("x: " & x & " ("& getMetadata(x).getName() & ")<br>");
/*** PARSEDATETIME OF STRING ***/
y = parseDateTime(dstr) ;
writeOutput("y: " & y & " ("& getMetadata(y).getName() & ")<br>");
</cfscript>
CF 2016 and lower
https://trycf.com/gist/c9c35dccb04f91cd6c06e4082ed306ca/acf2016?theme=monokai
Your database is giving the ColdFusion query back a Java object, which is going into the ParseDateTime function, and CF is doing its magic then giving you back a ColdFusion date object, which looks like a CF timestamp that is easily coerced into what you want it to display.
dobj: 2021-04-09 12:01:02.345 (java.sql.Timestamp)
x: {ts '2021-04-09 12:01:02'} (coldfusion.runtime.OleDateTime)
CF2021 (and CF2018)
https://trycf.com/gist/4c9bbc036a63a135962f0912b8591e00/acf2021?theme=monokai (trycf link for CF2021 seems to be defaulting to Lucee5, so you'll have to reselect CF2021)
It looks like the behavior changed slightly in CF2018. I don't know the inner workings of the ParseDateTime functions, but I'm assuming that in earlier versions, it would convert the date object to a date string before it converted it into a ColdFusion object on return. As of 2018, it appears that if it receives a Java data object, it recognizes that it's already a date object and just returns it (bypassing a conversion to a ColdFusion date string and then object). This is seems to be more in line with the originally stated behavior. And since the Java timestamp value doesn't have "{ts...", but CF does, it changes the way a string us ultimately created from the function's return value. This is possibly a compatibility bug (since the behavior is subtly different), but I'm not completely sure.
Regardless, it seems to be caused by the simple fact that ParseDateTime is being used here for something other than its intended purpose. Just like using TimeFormat(now(),"yyyy-MMM-dd hh:nn:ss"). ACF will return a string with the Year and Day masked, even though that's not something that TimeFormat() is intended for (NOTE: Lucee seems to handle it correctly). If a function is used in an unexpected manner, it shouldn't be expected to return consistent results in different versions.
And that's where I get kinda iffy on whether it should be a bug or not. In the past, most ColdFusion functions didn't much care if a "date" was a string or an object. It seems that CF2018+ does. Or at least treats them differently.
Ultimately, your code should probably be fixed to use functions the way they were meant to be used. However, I understand that might be a bit much. You might be able to fix your current issue by explicitly converting the query object into a string before you parse it.
ParseDateTime(qryDates.expiry_date.toString())
One other thing to note is that in CF2016, if your datetime value had a millisecond component, that would be stripped off in your final ParseDateTime value. However, in CF2021/18, since the Java value doesn't appear to be changed, the milliseconds component will still be in your return value. toString() should also fix that, and you'll get exactly what you had before.

Issue in matching java.util.Date using Hamcrest in Unit Test

I am writing a Test Case for a REST Controller. Code below:
private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yy");
#Test
public void getByExternalTransactionId() throws Exception {
EquityFeeds equityFeeds = new EquityFeeds(423,"SAPEXTXN1", "GS", "ICICI", "BUY", dateFormat.parse("22/11/13"), 101.9f, "BLO", "Y",0);
when(equityFeedsService.findByExternalTransactionId("SAPEXTXN1")).thenReturn(equityFeeds);
mockMvc.perform(MockMvcRequestBuilders.get("/equityFeeds/getByExternalTransactionId/{externalTransactionId}", "SAPEXTXN1"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.*", Matchers.hasSize(10)))
.andExpect(jsonPath("$.id", Matchers.is(423)))
.andExpect(jsonPath("$.externalTransactionId", Matchers.is("SAPEXTXN1")))
.andExpect(jsonPath("$.clientId", Matchers.is("GS")))
.andExpect(jsonPath("$.securityId", Matchers.is("ICICI")))
.andExpect(jsonPath("$.transactionType", Matchers.is("BUY")))
// .andExpect(jsonPath("$.transactionDate", Matchers.is(dateFormat.parse("22/11/13"))))
.andExpect(jsonPath("$.transactionDate", Matchers.is(Date.parse("22/11/13"))))
.andExpect(jsonPath("$.marketValue", Matchers.is(101.9f)))
.andExpect(jsonPath("$.sourceSystem", Matchers.is("BLO")))
.andExpect(jsonPath("$.priorityFlag", Matchers.is("Y")))
.andExpect(jsonPath("$.processingFee", Matchers.is(0)));
verify(equityFeedsService, times(1)).findByExternalTransactionId("1");
verifyNoInteractions(equityFeedsService);
}
Issue:
It's breaking in transactionDate which is java.util.Date in POJO. I have tried below in the test case:
.andExpect(jsonPath("$.transactionDate", Matchers.is(dateFormat.parse("22/11/13"))))
This gives me the output
java.lang.AssertionError: JSON path "$.transactionDate"
Expected: is <Fri Nov 22 00:00:00 IST 2013>
but: was <1385058600000L>
Expected :is <Fri Nov 22 00:00:00 IST 2013>
Actual :<1385058600000L>
Then I tried:
.andExpect(jsonPath("$.transactionDate", Matchers.is(Date.parse("22/11/13"))))
This gave me the output:
java.lang.AssertionError: JSON path "$.transactionDate"
Expected: is <1412965800000L>
but: was <1385058600000L>
Expected :is <1412965800000L>
Actual :<1385058600000L>
This looks to be very close. I understand that the difference in value is because the time the date was created in POJO is milliseconds is different from the time the date was created in the .andExpect(jsonPath("$.transactionDate", Matchers.is(Date.parse("22/11/13")))) lines and hence the values are different, as also the values are long since the values are in milliseconds.
My TestCase is failing only because of this field. I am really out of my mind as to how should I solve this. I have to use java.util.Date. Any others solution for this?
Edit: If I understand correctly (not familiar with Hamcrest), you need to feed an old-fashioned java.util.Date object into the EquityFeeds constructor and test that the long value that you get back out — 1385058600000L or 1 385 058 600 000 — agrees with the Date you specified.
java.time
To construct the java.util.Date that you need:
Instant transactionTime = LocalDate.of(2013, Month.NOVEMBER, 22)
.atStartOfDay(ZoneId.systemDefault())
.toInstant();
Date oldfashionedDate = Date.from(transactionTime);
System.out.println(oldfashionedDate);
Output so far when running in Asia/Kolkata time zone:
Fri Nov 22 00:00:00 IST 2013
Now just pass oldfashionedDate as the 6th argument to the EquityFeeds constructor. The point in the above lines of code is not only that we’re using the java.time, the modern Java date and time API, and it is very clear to read from the code what it does; it also makes testing easy. To produce the expected long value:
long expectedTransactionDateMillis = transactionTime.toEpochMilli();
System.out.println(expectedTransactionDateMillis);
1385058600000
Not being familiar with Hamcrest and not having tried I would expect that you just need to fill this value into your assertion:
.andExpect(jsonPath("$.transactionDate", Matchers.is(expectedTransactionDateMillis)))
The java.util.Date class is poorly designed and long outdated. I recommend you don’t use it, and I even more strongly recommend you don’t use the notoriously troublesome SimpleDateFormat class. Even though Date is used in your production code for historical reasons, I see no reason why you should repeat that mistake in your tests. Use java.time, it is so much nicer to work with. And conversions exist for when you need an object of one of the outdated types like Date.
What went wrong in your test?
Your first attempt:
.andExpect(jsonPath("$.transactionDate", Matchers.is(dateFormat.parse("22/11/13"))))
The result of dateFormat.parse("22/11/13") is a java.util.Date. Even though this is equal to the Date in your POJO, the value in your JSON is a long representing a count of milliseconds since the epoch (a practice you may want to change if you can). Since a Date and a long can never be equal, your test fails.
You then tried:
.andExpect(jsonPath("$.transactionDate", Matchers.is(Date.parse("22/11/13"))))
Now you are getting a long value alright. We can see that the expected and actual values have the same format in the printed output. There are two things wrong:
You are using the Date.parse method that has been deprecated since 1997. It has been so because it works unreliably across time zones. Even if you insisted on using Date, you should still stay far away from those deprecated methods and constructors.
Your date string gets parsed into 1 412 965 800 000, equal to 2014-10-11T00:00+05:30, so it’s nearly a year off. That method is not only deprecated, it is also confusing and parses your date string as the 11th day of the 22nd month of 2013. There is no 22nd month of the year, but the parse method just extrapolates, keeps counting months into 2014 and ends up with October that year. One more reason not to use that method.
Link
Oracle tutorial: Date Time explaining how to use java.time.

How can I get the current day in Robot Framework?

Im new to automated Testing.
Now I want to select the current weekday from a list.
I want to us following Keyword:
Selenium2Library.Select From List by Value ${day_of_the_week}
How can I get the Current day in Robot Framework? Is there a simple solution to my Problem?
The best would be a variable that gives me the current day in german Language.
I hope you can help me.
Using the Library DateTime
Which can be called by:
**** Settings ***
Library DateTime
You can use the Get Current Date keyword and assign it to a Var and specify the format. For example:
${CurrentDate} Get Current Date result_format=%d-%m-%Y
Log ${CurrentDate}
In your case you need to change the Result_format to retrieve the current day. This would be
${CurrentDay} Get Current Date result_format=%A
Log ${CurrentDay}
Which, when viewed in the log, would retrieve "Thursday"
The list of formats can be found here
Hope this helps you!
EDIT:
Due to the DateTime Library not supporting local names for the dates (Montag for Monday in German for instance) The Asker switched to the %w format to return 0-6 range. Then used an index to change the int into a string of the date!

Modify date time to a specific format

I'm having trouble coding a conversion to a specific time format along with converting to string format. I have the following code.
txtMonday->Text = Convert::ToString(dtpMondayIn->Value);
I want txtMonday(text box) not only to display dtpMondayIn's value(datetimepicker), but in h.mm format. Currently, it will display the date and time, for example, January 1, 2014 8:40:30 AM. I want the text box to show only 8.40 as in hours and minutes. How could I code this? I'm using Visual Studio 2012 and c++ language.
I am not really sure but
try this,
txtMonday->Text = Convert::ToString(dtpMondayIn->Value.ToString("hh:mm tt",CultureInfo.InvariantCulture));
OR
Convert::ToString(dtpMondayIn->Value.ToString("hh:mm",CultureInfo.InvariantCulture));
Also check DATETIME PICKER VALUE PROP
and DATETIME FORMATS
Let me know in case it works.

Library to discover dates from text?

I need to pull a date out of a string. Since not everyone uses the official ISO format when printing their dates, it is impractical to write a date parser for every possible date format that could be used, and I need to handle as many date formats as possible - I don't control the data and can't expect it to come in a specific format.
This seems like a problem that has probably already been solved ages ago, but my Google-fu is too weak to find the solution. :(
Does there already exist a C++ library that, given a string, will return the month, day, year, hour, minute, second, etc that is referenced in that string, if any?
Pseudocode:
string s1 = "There is an expected meteor shower this Thursday,"
"August 15th 2013 at 4:39 AM.";
string s2 = "20130815T04:39:00";
date d1 = magicConverter(s1);
date d2 = magicConverter(s2);
assert(d1 == d2);
You might use the code from here, but you need to configure a mask, that tells the code which time format is used. If you write a class routine, that takes a mask and a string and gets you out the time and is able to print in any format you like, you should be well prepared. You have to look in more detail, if it also supports Daynames and Monthnames. I got it to work in python with a module providing a function that seems pretty much the same.
For more detail:
Please look at the example 2013-08-03 again. Nobody and as follows no computer is able to tell you if this date belongs to August or April, except of having a mask telling JJJJ-MM-DD or JJJJ-DD-MM. Also this library may tell you only standard masked times. So it might lead you to August in this case. But as you said it can be any date declaration, thus it does not need to follow standards, thus it can also mean March. An other possibility is to tell you about the date from the context (e.g. a table with a column of all te same time formats by looking for the increase (which would also fail if you just look at one day per month for just one year).
Another example... if I ask you 2013-05-04... to which month does it belong? You might tell me... April. I would reply "no, to the 4th of May" and vice versa for May and 5th of April. If you tell me how to solve this puzzle with two possible solutions I would understand your downvote... please think before downvoting someone trying to help you.