Why does this unit test fail when testing DateTime equality? - unit-testing

Using NUnit 2.2 on .NET 3.5, the following test fails when using DateTime.Equals. Why?
[TestFixture]
public class AttributeValueModelTest
{
public class HasDate
{
public DateTime? DateValue
{
get
{
DateTime value;
return DateTime.TryParse(ObjectValue.ToString(), out value) ? value : new DateTime?();
}
}
public object ObjectValue { get; set; }
}
[Test]
public void TwoDates()
{
DateTime actual = DateTime.Now;
var date = new HasDate {ObjectValue = actual};
Assert.IsTrue(date.DateValue.Value.Equals(actual));
}
}

The dates aren't equal. TryParse drops some ticks. Compare the Tick values.
For one test run:
Console.WriteLine(date.DateValue.Value.Ticks);
Console.WriteLine(actual.Ticks);
Yields:
633646934930000000
633646934936763185

The problem isn't really TryParse, but actually ToString().
A DateTime object starts with precision (if not accuracy) down to millionth of seconds. ToString() convertsit into a string, with precision only to a second.
TryParse is doing the best it can with what it is given.
If you add a format specifier (along the lines of "yyyy-MM-dd HH:mm:ss.ffffff"), it should work.

To specify a format that includes all the precision, you can use the String.Format() method. The example that James gives would look like this:
String.Format("{0:yyyy-MM-dd HH:mm:ss.ffffff}", ObjectValue);
I don't know what that will do when you pass it something that's not a date.
Perhaps a simpler approach is to add a special case when you've already got a date object:
public DateTime? DateValue
{
get
{
DateTime value = ObjectValue as DateTime;
if (value != null) return value;
return DateTime.TryParse(ObjectValue.ToString(), out value) ? value : new DateTime?();
}
}

public DateTime? DateValue
{
get
{
DateTime value;
bool isDate = DateTime.TryParse(ObjectValue.ToString(), out value);
return isDate ? new DateTime?(value) : new DateTime?();
}
}

I don't know if this is the same in .NET, but in Java the equals often will only compare if the instances are the same, not if the values are the same. You'd instead want to use compareTo.

Related

Flutter convert List<List<dynamic>>

I have a Flutter app in which I make an http request, which brings me json data. Afer formatting it with a package I get a list of lists of dynamic type. Here´s what it looks like:
[[2016-04-01, 85.5254], [2016-05-01, 89.1118], [2016-06-01, 91.8528], [2016-07-01, 93.7328], [2016-08-01, 93.9221], [2016-09-01, 95.0014], [2016-10-01, 97.2428], [2016-11-01, 98.8166]]
So I created a class named IpcData, which recieves a String and a double.
class IpcData {
final String date;
final double value;
IpcData(this.date, this.value);
}
So we could guess that an IpcData instance would look like the following:
IpcData(2016-08-01, 93.9221)
I can´t figure out how, but I´d like to have a method that using the information from the List<List<dynamic>> to return a List<IpcData>, that would looke like:
[IpcData(2016-08-01, 93.9221), IpcData(2016-08-01, 93.9221), IpcData(2016-08-01, 93.9221),]
You can use .map function on the original list to construct the new one. Something like this.
class IpcData {
final String date;
final double value;
IpcData(this.date, this.value);
#override
String toString() {
return '$date -> $value';
}
}
void main() {
List<List<dynamic>> initList = [
['2016-04-01', 85.5254], ['2016-05-01', 89.1118], ['2016-06-01', 91.8528],
['2016-07-01', 93.7328], ['2016-08-01', 93.9221], ['2016-09-01', 95.0014],
['2016-10-01', 97.2428], ['2016-11-01', 98.8166], ['2016-12-01', 99.8166]
];
List<IpcData> ipcList = initList.map((e) => IpcData(e[0], e[1])).toList();
print(ipcList);
}

Using Univocity, how can I convert a date string value to a Date type in Java

I'll like to parse column zero in a csv file to a particular datatype, in this example a Date Object.
The method below is what I use currently to parse a csv file but I don't know how to incorporate this requirement.
import java.sql.Date;
public class Data {
#Parsed(index = 0)
private Date date;
}
}
public <T> List<T> convertFileToData(File file, Class<T> clazz) {
BeanListProcessor<T> rowProcessor = new BeanListProcessor<>(clazz);
CsvParserSettings settings = new CsvParserSettings();
settings.setProcessor(rowProcessor);
settings.setHeaderExtractionEnabled(true);
CsvParser parser = new CsvParser(settings);
parser.parseAll(file);
return rowProcessor.getBeans();
}
All you need is to define the format(s) of your date and you are set:
#Format(formats = {"dd-MMM-yyyy", "yyyy-MM-dd"})
#Parsed(index = 0)
private Date date;
}
As an extra suggestion, you can also replace a lot of your code by using the CsvRoutines class. Try this:
List<T> beanList = new CsvRoutines(settings).parseAll(clazz, file);
Hope it helps.

Can I change the current date and time for a specific process?

Is there a way to change the date and time seen by a specific process as opposed to the entire computer (i.e. the time returned by time() in C, by DateTime.Now in C#, by datetime.now() in Python, by new Date() in JavaScript, by System.currentTimeMillis() in Java, etc.)?
For instance, is there a way to fool a program into thinking it's midnight while it's 7 AM on the rest of the computer, or to make it think it's Christmas or Leap Day while the system clock shows July 18th?
An applicable situation would be when you're writing unit tests and you want to quickly test any special behavior the program has on Christmas or on Leap Day or on the demo's expiration date, and you want to test this behavior without having to use the date changing function in the OS and interfere with programs that rely on the date being correct (much less forcing me to have superuser privileges over the computer).
Previously mentioned Typemock also has an API for C++, which also allows you to fake time, in C++:
TEST_METHOD(FakeCurrentTime)
{
SYSTEMTIME fakeTime;
fakeTime.wYear = 2000;
fakeTime.wMonth = 1;
fakeTime.wDay = 1;
FAKE_GLOBAL(GetSystemTime);
WHEN_CALLED(GetSystemTime(RET(&fakeTime))).Ignore();
SYSTEMTIME now;
GetSystemTime(&now);
Assert::IsTrue(now.wMilliseconds - fakeTime.wMilliseconds == 0);
}
I don't think you can do what you want to do in C#. There aren't any hooks that I know of to make DateTime.Now return arbitrary values out of the box. The standard way to implement unit testing that is time sensitive is to create a time provider interface. This is the approach taken by third party libraries such as Noda Time that values testing time related functions. One such implementation is below (not Noda Time compatible):
public ITimeProvider
{
DateTime CurrentTime { get; }
DateTime CurrentUtcTime { get; }
}
public DefaultTimeProvider : ITimeProvider
{
public DateTime CurrentTime { get { return DateTime.Now; } }
public DateTime CurrentUtcTime { get { return DateTime.UtcNow; } }
}
Then when you want to unit test the code you replace the DefaultTimeProvider implementation with a mock implementation. You can use your favorite mocking framework or just write something like this:
public MockTimeProvider : ITimeProvider
{
private readonly DateTime _currentTime;
private readonly DateTime _currentUtcTime;
public MockTimeProvider(DateTime currentTime, DateTime currentUtcTime)
{
_currentTime = currentTime;
_currentUtcTime = currentUtcTime;
}
public DateTime CurrentTime { get { return _currentTime; } }
public DateTime CurrentUtcTime { get { return _currentUtcTime; } }
}
Disclaimer, I work at Typemock.
You can use Typemock Isolator for this:
[TestMethod]
public void isLicenseExpiredTest()
{
Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2017, 5, 4));
bool result = Licenses.IsLicenseExpired();
Assert.IsFalse(result);
}
public static class Licenses
{
public static bool IsLicenseExpired()
{
if (DateTime.Now > new DateTime(2016, 5, 4))
{
return false;
}
else
{
return true;
}
}
}
java.time
Java 8 and later has the java.time framework built in. Supplants the old date-time classes.
Clock
Includes the Clock class. You can override this class to make your own faked current time.
A few alternate implementations are included via static methods. You can ask for a Clock that stays fixed on a single moment you specify. You can shift the current time by some specified amount. And you have the Clock report the current moment rounded to the whole second or minute and so on.

PETAPOCO - Invalid object name

I am using CTE with PetaPOCO and getting a strange error
SQL Exception: Invalid Object Name PayTransactionForRollingVacationAverage that references the model that the data should map to.
The code is as follows.
public IEnumerable<PayTransactionForRollingVacationAverage> GetPayTransactionForRollingVacationAverage(DateTime payEndingDate)
{
PointsNorth.PetaPoco.Sql sql = new PointsNorth.PetaPoco.Sql();
sql.Append(#"
;with HolidayWeeks as
(
Select Distinct EmployeeId, PayEndDate, 'Y' as HolidayWeek
from PayTransactions
where PayEndDate = #payEndingDate
and LaborCode in ('251', '249')
)", new { payEndingDate });
sql.Append(#"
Select
PT.EmployeeId,
PT.PayEndDate,
J.JobClass,
PayCodes.AverageRateCode,
PT.RegularHours,
PT.RegularRate,
PT.RegularAmount
from PayTransactions PT
Left Outer Join PayCodes on PayCodes.PayCodeCode = PT.LaborCode
Left Outer Join HolidayWeeks as H on H.PayEndDate = PT.PayEndDate and H.EmployeeId = PT.EmployeeId
Inner Join Jobs as J on J.JobId = PT.JobId
where PT.PayEndDate = #payEndingDate
and IsNull(H.HolidayWeek, 'N') <> 'Y'
order by PT.EmployeeId, PT.PayEndDate, J.JobClass", new { payEndingDate });
var data = Database.Query<PayTransactionForRollingVacationAverage>(sql);
return data;
}
The model is pretty simple:
public class PayTransactionForRollingVacationAverage
{
public long EmployeeId { get; set; }
public DateTime PayEndDate { get; set; }
public string JobClass { get; set; }
public string AverageRateCode { get; set; }
public decimal RegularHours { get; set; }
public decimal RegularRate { get; set; }
public decimal RegularAmount { get; set; }
}
I tried breaking the SQL up to make sure it was building correctly, but I still get the error. Any idea why this is occurring?
Remove the whitespace before the semi-colon.
According to Alex Jorgenson's link, this is fixed if you make a semi-colon the very first character.
According to my testing, this is strictly the first character, i.e. if there is even some whitespace before the semi-colon, the auto-generated code will still be spit out.
This is a known issue with Peta Poco. It appears to be fixed in some version but I don't know which one. You can find more information and a work around for this particular issue at https://github.com/toptensoftware/PetaPoco/issues/22

Entity 4.0 Casting Value As DateTime

LINQ to Entity Framework 4.0. SQL Server.
I'm trying to return a list of objects and one of the columns in the database is varchar(255) and contains dates. I'm trying to cast the value to datetime, but I haven't found the solution to that yet.
Example:
List<MyObject> objects = (from c in context.my_table
where c.field_id == 10
select new MyObject()
{
MyDate = c.value // This is varchar, want it to be datetime
}).ToList();
Is this not possible?
Update. This is LINQ to Entity. When trying to convert to DateTime I get:
LINQ to Entities does not recognize the method 'System.DateTime ToDateTime(System.String)' method, and this method cannot be translated into a store expression.
The answer is it's not currently possible with Entity Framework. With LINQ itself it is, just not supported with Entity Framework.
You want DateTime.Parse(c.value) which will take a string containing a date and create a DateTime object out of it.
you can do like this
Date=DateTime.Parse(text)
read, And the best bet would be using your result and then Converting to date time. Like below,
static void Main(string[] args)
{
Console.WriteLine(getme());
Console.ReadLine();
}
private static DateTime getme()
{
List<string> ss = new List<string>();
ss.Add("11/11/2010");
var r = from l in ss
select new { date = Convert.ToDateTime(l) };
return r.FirstOrDefault().date;
}