Why conversion between default system datetime to PersianCalendar is not working? - c#

I have a dateTime stored in database using this line of code:
var now=DateTime.Now;
so after it stored, the data is like this in database and also after recalling the entity:
2019-01-26 17:27:46.297
when i try to convert it to another culture datetime using this method:
public static string ToPersianDate(this DateTime t)
{
var pc = new PersianCalendar();
return $"{pc.GetYear(t)}/{pc.GetMonth(t)}/{pc.GetDayOfMonth(t)}";
}
after using this method :
var persianDate=now.ToPersianDate();
I get this string as a result:
2019/01/26
But I expected to get this result:
1397/11/06

Here is a complete example that converts time to PersianCalender,
using System;
using System.Globalization;
namespace ConsoleApp1
{
public class Program
{
public static void Main(String[] args)
{
var date = DateTime.Now;
var str = date.ToPersianDate();
Console.WriteLine(str);
Console.Read();
}
}
public static class Extender
{
public static string ToPersianDate(this DateTime t)
{
var pc = new PersianCalendar();
return $"{pc.GetYear(t)}/{pc.GetMonth(t)}/{pc.GetDayOfMonth(t)}";
}
}
}
your problem its not reproducible, code is attached for further reference

Related

Generic type and field accessing in C#

Instead of T (Type) if I use class name i.e. sampleclass this code works properly,
but if I use T, then it shows that
'T' does not contain a definition for 'TimeStamp' and no accessible
extension method 'TimeStamp' accepting a first argument of type 'T'
could be found (are you missing a using directive or an assembly
reference?)
//Get collection.
var collection = this.GetDatabaseConnection().GetCollection<T>
(collectionName);
//filter to read specific data.
var filter = Builders<T>.Filter.Where(result => result.TimeStamp >=
startTime && result.TimeStamp <= endTime);
List < T > queryData = collection.Find<T>(filter, null).ToList();
Previously it was as follows and working finely:
//Get collection.
var collection = this.GetDatabaseConnection().GetCollection<Sampleclass>.
(collectionName);
//filter to read data using specific timestamp.
var filter = Builders<Sampleclass>.Filter.Where(result =>
result.TimeStamp >=
startTime && result.TimeStamp <= endTime);
List < Sampleclass > queryData = collection.Find<Sampleclass>
(filter, null).ToList();
i would do it using a base class like this
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using System;
using System.Linq;
namespace StackOverflow
{
public class Program
{
public class Entity
{
[BsonId]
public ObjectId Id { get; set; }
public DateTime TimeStamp { get; set; }
}
public class Sample : Entity
{
public string Something { get; set; }
}
private static void Main(string[] args)
{
var collection = new MongoClient("mongodb://localhost:27017")
.GetDatabase("Test")
.GetCollection<Entity>("Samples");
var sample = new Sample
{
Id = ObjectId.GenerateNewId(),
Something = "something",
TimeStamp = DateTime.UtcNow
};
collection.InsertOne(sample);
var result = collection.AsQueryable()
.Where(s =>
s.TimeStamp >= DateTime.UtcNow.AddMinutes(-1) &&
s.TimeStamp <= DateTime.UtcNow.AddMinutes(1))
.ToArray();
}
}
}
The problem is that T doesn't have a TimeStamp property as it's a generic type. If you always have to access the TimeStamp of whatever type you process in your collection, you could consider using an interface that has TimeStamp as a get function. All the types you want to process would have to implement that interface.
public interface MyInterface
{
TimeSpan TimeStamp { get; } //or whatever type your are using for your TimeStamp property
}
var collection = this.GetDatabaseConnection().GetCollection<MyInterface>
(collectionName);
var filter = Builders<MyInterface>.Filter.Where(result => result.TimeStamp >=
startTime && result.TimeStamp <= endTime);
List<MyInterface> queryData = collection.Find<MyInterface>(filter,null).ToList();
This way it's still quite generic. If you want to still use type T you would have to work with reflection to find the property TimeStamp on your processed type.
Edit: Some advice for using type T: You always have to consider that T can be anything, from an integer to any other object imaginable. Sometimes it can be quite useful if you have a method for example that doesn't need to access any properties on the type T object it is given but is used for many different types. I lately used T to build a little ParseOrDefault method to catch values that can't be converted:
private T ParseOrDefault<T>(Object value, T defaultValue)
{
try
{
return (T)Convert.ChangeType(value, typeof(T));
}
catch (Exception)
{
return defaultValue;
}
}
As soon as you have to deal with more specific use cases T is mostly not that useful.
after reading your comments on my first answer, i'd like to propose the following solution using MongoDB.Entities
hope this is more or less what you're trying to achieve...
using MongoDB.Entities;
using System;
using System.Collections.Generic;
namespace StackOverflow
{
public class Program
{
public class MySample : Entity
{
public DateTime TimeStamp { get; set; }
}
public class Sample1 : MySample
{
public string SomeProp { get; set; }
}
public class Sample2 : MySample
{
public string AnotherProp { get; set; }
}
private static void Main(string[] args)
{
new DB("test");
var sample1 = new Sample1 { SomeProp = "some prop value", TimeStamp = DateTime.UtcNow };
var sample2 = new Sample2 { AnotherProp = "another prop", TimeStamp = DateTime.UtcNow };
DB.Save(sample1);
DB.Save(sample2);
var s1 = FindSamples<Sample1>();
var s2 = FindSamples<Sample2>();
List<T> FindSamples<T>() where T : MySample
{
return DB.Find<T>()
.Many(s =>
s.TimeStamp >= DateTime.UtcNow.AddMinutes(-1) &&
s.TimeStamp <= DateTime.UtcNow.AddMinutes(1));
}
}
}
}

How do I access members of a class in C# like I think I could do in c++?

How do I access members of a class in C# like I think I could do in c++ ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace DateAndMoney
{
class InputNode
{
DateTime dateTime;
string dollarAmount;
}
class Program
{
public static void ReadFile(string filename)
{
InputNode inputNode = new InputNode();
if (System.IO.File.Exists(filename))
{
var reader = new StreamReader(File.OpenRead(filename));
while (!reader.EndOfStream)
{
var input = reader.ReadLine();
var values = input.Split(',');
inputNode.dateTime = values[0];
inputNode.dollarAmount = values[1];
}
}
}
static void Main(string[] args)
{
string filename;
Console.WriteLine("enter path and file name of input file");
filename = Console.ReadLine();
ReadFile(filename);
}
}
}
The precompiler does not like:
inputNode.dateTime = values[0];
inputNode.dollarAmount = values[1];
And this change changes nothing
struct InputNode
{
DateTime dateTime;
string dollarAmount;
}
If you change
class InputNode
{
DateTime dateTime;
string dollarAmount;
}
to
class InputNode
{
public DateTime dateTime;
public string dollarAmount;
}
You can then access them as you were trying, although you'd need to convert your text to date to put it in the date time.
By default in C# fields are private, so you can't access it. Better to use Properties to set and get values
In your case:
class InputNode
{
public DateTime DateTime{get;set;}
public string DollarAmount{get;set}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace DateAndMoney
{
public class InputNode
{
public DateTime dateTime;
public string dollarAmount;
}
public class Program
{
public static void ReadFile(string filename)
{
InputNode inputNode = new InputNode();
if (System.IO.File.Exists(filename))
{
var reader = new StreamReader(File.OpenRead(filename));
while (!reader.EndOfStream)
{
var input = reader.ReadLine();
var values = input.Split(',');
try
{
inputNode.dateTime = Convert.ToDateTime(values[0]);
inputNode.dollarAmount = Convert.ToDouble(values[1]);
}
catch(Exception e)
{}
}
}
}
public static void Main(string[] args)
{
string filename;
Console.WriteLine("enter path and file name of input file");
filename = Console.ReadLine();
ReadFile(filename);
}
}
}
This did it.
class InputNode
{
public DateTime dateTime;
public string dollarAmount;
}
class Program
{
public static void ReadFile(string filename)
{
InputNode inputNode = new InputNode();
if (System.IO.File.Exists(filename))
{
var reader = new StreamReader(File.OpenRead(filename));
while (!reader.EndOfStream)
{
var input = reader.ReadLine();
var values = input.Split(',');
inputNode.dateTime = Convert.ToDateTime(values[0]);
inputNode.dollarAmount = values[1];
}
}
}
First of all ( as everyone else said ) you need to make the fields "visible" for the rest of the application.
class InputNode
{
// DateTime dateTime;
internal DateTime dateTime;
public string dollarAmount;
// string dollarAmount;
}
You can read more about access modifiers here
Second thing is that you're assigning string to the DateTime type field. In C# you have bunch of converters which can cast from one type into another and also you can create your own converters using this example
You could create public method, which returns the value of a particular member (recommended) or make the members themselves public.
You can use for reference (https://msdn.microsoft.com/en-us/library/st6sy9xe.aspx)
class InputNode
{
private DateTime dateTime;
private string dollarAmount;
public DateTime GetDate()
{
return dateTime;
}
}

C# Constructor of class initialising and running script

Got some strange behaviour with a script, the constructor of my FileHandler class appears to be calling the class and running the script.
The class itself is only being referenced in VS15 once and that is by its constructor, the main method has not yet even have an object of FileHandler, which is not mentioned anywhere else in the code.
Surely this code should not be running?
Edit: I placed a breakpoint at the start of the Program.cs and began stepping through, but when I did this I noticed that the public class FileHandler becomes class Program and my constructor is 'replaced' by a Main method.
Is this something that C# does by design?
Programs.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using QuantConnect;
using QuantConnect.Securities;
using QuantConnect.Securities.Forex;
namespace TradingDaysFileChecker
{
class Program
{
static void Main(string[] args)
{
var securityType = SecurityType.Forex;
var ticker = TickType.Trade;
var marketHoursDatabase = MarketHoursDatabase.FromDataFolder();
var market = Market.FXCM;
var symbol = Symbol.Create(ticker.ToString(), securityType, market);
var marketHoursDbEntry = marketHoursDatabase.GetEntry(symbol.ID.Market, symbol.Value, symbol.ID.SecurityType);
var exchange = new ForexExchange(marketHoursDbEntry.ExchangeHours);
Console.ReadLine();
}
}
}
FileHandler.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using QuantConnect.Securities.Forex;
namespace TradingDaysFileChecker
{
public class FileHandler
{
private readonly StreamWriter _writeToFile;
private readonly List<Tuple<string, string>> _missingDays;
private readonly string _dataFilePath;
private readonly DateTime _startDate;
private readonly DateTime _endDate;
private readonly ForexExchange _exchange;
private readonly IEnumerable<DateTime> _validTradingDays;
private readonly string[] _forexSecuritiesFolders;
public FileHandler(ForexExchange exchange)
{
_startDate = new DateTime(2007, 04, 01);
_endDate = new DateTime(2016, 07, 25);
_exchange = exchange;
_writeToFile = new StreamWriter(#"C:\Users\RichardsPC\Documents");
_dataFilePath = #"C:\Users\RichardsPC\Desktop\export\exporter\forex\fxcm\minute\";
_forexSecuritiesFolders = Directory.GetDirectories(_dataFilePath);
_missingDays = new List<Tuple<string, string>>();
_validTradingDays = IterateOverDateRange(_exchange, _startDate, _endDate);
}
public void CheckForMissingFiles()
{
foreach (var validDay in _validTradingDays)
{
foreach (var forexSecurity in _forexSecuritiesFolders)
{
var fxPair = new DirectoryInfo(forexSecurity).Name;
var formattedDate = FormatDate(validDay);
var path = SetPath(_dataFilePath, fxPair, formattedDate);
if (!File.Exists(path))
{
_missingDays.Add(Tuple.Create(fxPair, formattedDate));
}
}
}
Results();
}
public void Results()
{
if (_missingDays.Count > 0)
{
foreach (var missingDay in _missingDays.OrderBy(md => md.Item1))
{
var formattedTupleOutput = missingDay.ToString().TrimStart('(').TrimEnd(')');
Console.WriteLine(formattedTupleOutput);
WriteResultsToFile(formattedTupleOutput);
}
}
else
{
var noFilesMissing = "No results missing";
Console.WriteLine(noFilesMissing);
WriteResultsToFile(noFilesMissing);
}
Console.WriteLine("Records missing: " + _missingDays.Count);
}
public void WriteResultsToFile(string result)
{
_writeToFile.WriteLine(result);
}
public static string FormattedFileName(string tradingDay)
{
return tradingDay + "_quote.zip";
}
public string FormatDate(DateTime validDay)
{
return validDay.ToString("yyyyMMdd");
}
public static string SetPath(string dataFilePath, string fxPair, string formattedDate)
{
return dataFilePath + fxPair + #"\" + FormattedFileName(formattedDate);
}
public IEnumerable<DateTime> IterateOverDateRange(ForexExchange exchange, DateTime start, DateTime end)
{
for (var day = start.Date; day.Date <= end.Date; day = day.AddDays(1))
if (exchange.IsOpenDuringBar(day.Date, day.Date.AddDays(1), false))
{
yield return day;
}
}
}
}
I figured out what was happening.
I had an old version of TradingDaysFileChecker.cs in the Documents folder of my system that I had backed up for some reason.
In that version all the file handling logic was inside Program.cs.
I refactored and extracted out the file handling to the new class.
For some reason when I was running the script, it was still using that old copy, even though it was not in the solution folder.
That's why the change in the class name and appeared to happen, it was jumping into the Program.cs and Main method of that other file, pulling it up from my Documents folder.
How that happened, I do not know.
I deleted the file from my Documents folder and now it is behaving correctly.

Merge two list of TimeRanges into one

I have a class named TimeRange and another Interval both have same following structure
public class TimeRange
{
public TimeOfDay start{get; set;}
public TimeOfDay end{get; set;}
}
I have two list
List<TimeRange> timeRanges = new List<TimeRange>();
timeRanges.Add(new TimeRange(Timespan.FromHours(5), Timespan.FromHours(6)));
timeRanges.Add(new TimeRange(Timespan.FromHours(8), Timespan.FromHours(9)));
List<Interval> interval = new List<Interval>();
interval.Add(new Interval(Timespan.FromHours(1), Timespan.FromHours(7)));
interval.Add(new Interval(Timespan.FromHours(10), Timespan.FromHours(15)));
I want to merge these lists into one so that final result will contain this
Timespan.FromHours(1), Timespan.FromHours(5)
Timespan.FromHours(5), Timespan.FromHours(6)
Timespan.FromHours(6), Timespan.FromHours(7)
Timespan.FromHours(8), Timespan.FromHours(9)
Timespan.FromHours(10), Timespan.FromHours(15)
Another case:
timeRange.Add(new Interval(TimeSpan.FromHours(9), TimeSpan.FromHours(17))
timeRange.Add(new Interval(TimeSpan.FromHours(17), TimeSpan.FromHours(19))
interval.Add(new Interval(TimeSpan.FromHours(0), TimeSpan.FromHours(4))
interval.Add(new Interval(TimeSpan.FromHours(4), TimeSpan.FromHours(5))
interval.Add(new Interval(TimeSpan.FromHours(5), TimeSpan.FromHours(9))
interval.Add(new Interval(TimeSpan.FromHours(9), TimeSpan.FromHours(10))
interval.Add(new Interval(TimeSpan.FromHours(12), TimeSpan.FromHours(13))
Expected Result:
Timespan.FromHours(0), Timespan.FromHours(4)
Timespan.FromHours(4), Timespan.FromHours(5)
Timespan.FromHours(5), Timespan.FromHours(9)
Timespan.FromHours(9), Timespan.FromHours(10)
Timespan.FromHours(10), Timespan.FromHours(12)
Timespan.FromHours(12), Timespan.FromHours(13)
Timespan.FromHours(13), Timespan.FromHours(17)
Timespan.FromHours(17), Timespan.FromHours(19)
After realizing I was thinking about this problem in the wrong way I came to an approach that should work in most scenarios. If you come across some data that this doesn't work on please provide it to me and I'll fix it. Thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
List<TimeRange> timeRanges = new List<TimeRange>();
timeRanges.Add(new TimeRange(TimeSpan.FromHours(2), TimeSpan.FromHours(3)));
timeRanges.Add(new TimeRange(TimeSpan.FromHours(8), TimeSpan.FromHours(9)));
timeRanges.Add(new TimeRange(TimeSpan.FromHours(1), TimeSpan.FromHours(5)));
timeRanges.Add(new TimeRange(TimeSpan.FromHours(3), TimeSpan.FromHours(6)));
List<Interval> intervals = new List<Interval>();
intervals.Add(new Interval(TimeSpan.FromHours(1), TimeSpan.FromHours(7)));
intervals.Add(new Interval(TimeSpan.FromHours(10), TimeSpan.FromHours(15)));
timeRanges.AddRange(intervals.Select(x => new TimeRange(x.start, x.end)));
timeRanges = TimeRange.ResolveOverlaps(timeRanges);
timeRanges.ForEach(x => Console.WriteLine($"{x.start} - {x.end}"));
Console.Read();
}
}
public class TimeRange
{
public TimeSpan start { get; set; }
public TimeSpan end { get; set; }
public TimeRange(TimeSpan st, TimeSpan en)
{
start = st;
end = en;
}
public static List<TimeRange> ResolveOverlaps(List<TimeRange> timeRanges)
{
var times = new List<TimeSpan>();
times.AddRange(timeRanges.Select(x => x.start));
times.AddRange(timeRanges.Select(x => x.end));
times = times.Distinct().OrderBy(x => x.Ticks).ToList();
timeRanges.Clear();
while (times.Count > 1)
{
timeRanges.Add(new TimeRange(times[0], times[1]));
times.RemoveAt(0);
}
return timeRanges;
}
}
public class Interval
{
public TimeSpan start { get; set; }
public TimeSpan end { get; set; }
public Interval(TimeSpan st, TimeSpan en)
{
start = st;
end = en;
}
}
}

the binary expression cannot be converted to a predicate expression in LINQ

I want to get the week number of a certain given DateTime.
public static int WeekOf(DateTime? date)
{
if (date.HasValue)
{
GregorianCalendar gCalendar = new GregorianCalendar();
int WeekNumber = gCalendar.GetWeekOfYear(date.Value, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return WeekNumber;
}
else
return 0;
}
And then I use the above method in:
public static List<ExpressionListDictionary> MyMethod(int weeknr)
{
using (DataAccessAdapter adapter = CreateAdapter())
{
LinqMetaData meta = new LinqMetaData(adapter);
var q = (from i in meta.Test
where WeekOf(i.StartDate) == weeknr
select new ExpressionListDictionary()
{
{"SomeId", i.Id}
}
);
return q.ToList();
}
}
And finally:
List<ExpressionListDictionary> someIDs = MyMethod(weeknr);
/* weeknr = 19 -> step by step debugging */
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryConstructionException: The binary expression '(WeekOf(Convert(EntityField(LPLA_1.StartDate AS StartDate))) == 19)' can't be converted to a predicate expression.
I do get the title error at return q.ToList(); . How can I achieve this?
I haven't ever used the LLBLGen library/framework... But probably this is the same problem that happens with Entity Framework/LINQ-to-SQL: you can't put in a query C# methods: the query must be executed by your db server, not locally, and your db server doesn't know how to execute C# code. So the problem would be in the
**WeekOf(i.StartDate)** == weeknr part of code (that is the only BinaryExpression of your query)
The exception you have posted is quite clear that the point of the error is the one that I have suggested. Then the reason is probably the one I gave you.
Taken from https://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=22861
If you are using SQL Server, that supports DATEPART(isowk, ...) (or if you have MySQL, that supports WEEK(...))
public class SQLFunctionMappings : FunctionMappingStore
{
public SQLFunctionMappings()
{
Add(new FunctionMapping(
typeof(SQLFunctions),
"WeekOf",
1,
"DATEPART(isowk, {0})") // For SQL Server
// "WEEK({0}, 1)") For MySQL
);
}
}
public class SQLFunctions
{
public static int? WeekOf(DateTime? date)
{
return null;
}
}
and then you would use it like:
Where there is the row with LinqMetaData meta = new LinqMetaData(adapter), add:
meta.CustomFunctionMappings = new SQLFunctionMappings();
and change the where:
where SQLFunctions.WeekOf(i.StartDate) == weeknr
Here there is the list of the functions already mapped by llblgen, and how to map other functions.
you can try to Make the method you have WeekOf takes string instead of Datetime?
public static int WeekOf(String dateAsString)
{
//if (!string.IsNullOrEmpty(dateAsString))
if (!dateAsString.equals(string.empty))
{
GregorianCalendar gCalendar = new GregorianCalendar();
int WeekNumber = gCalendar.GetWeekOfYear(date.Value, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return WeekNumber;
}
else
return 0;
}
And then you use the above below in:
public static List<ExpressionListDictionary> MyMethod(int weeknr)
{
using (DataAccessAdapter adapter = CreateAdapter())
{
LinqMetaData meta = new LinqMetaData(adapter);
var q = (from i in meta.Test
where i.startDate != null && WeekOf(i.StartDate.tostring()) == weeknr
select new ExpressionListDictionary()
{
{"SomeId", i.Id}
}
);
return q.ToList();
}
}
Try something like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyMethod(5);
}
public static int WeekOf(DateTime? date)
{
if (date.HasValue)
{
GregorianCalendar gCalendar = new GregorianCalendar();
int WeekNumber = gCalendar.GetWeekOfYear(date.Value, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
return WeekNumber;
}
else
return 0;
}
public static List<ExpressionListDictionary> MyMethod(int weeknr)
{
using (DataAccessAdapter adapter = CreateAdapter())
{
LinqMetaData meta = new LinqMetaData(adapter);
List<ExpressionListDictionary> q = (from i in meta.Test
where WeekOf(i.StartDate) == weeknr
select new ExpressionListDictionary()
{
Id = "SomeId"
}
).ToList();
return q;
}
}
public static DataAccessAdapter CreateAdapter()
{
return new DataAccessAdapter();
}
}
public class ExpressionListDictionary
{
public string Id { get; set; }
}
public class LinqMetaData
{
public List<LinqMetaData> Test {get;set;}
public DateTime StartDate {get;set;}
public int Id { get; set; }
public LinqMetaData(DataAccessAdapter adapter)
{
}
}
public class DataAccessAdapter : IDisposable
{
public void Dispose()
{
}
}
}
​

Categories

Resources