In my C# console application project I'm using MongoDB.Driver.2.4.3 with connection to MongoDB 3.2.10.
How would I convert "playerInBrazil.birthdate" in my code which is defined as BsonDateTime (I believe this is in UTC) to my local datetime value (Eastern Standard Time)?
I was trying to do subtract operation(not allowed) and DateTime.ToLocalTime Method () but couldn't make it work.
static void Main(string[] args)
{
DateTime myTimeConvert = DateTime.Now;
var client = new MongoClient("mongodb://localhost:27017");
var DB = client.GetDatabase("football");
var players = DB.GetCollection<Player>("players");
var playersInBrazil = players.AsQueryable()
.Where(p => p.country == "Brazil");
foreach (var playerInBrazil in playersInBrazil)
{
Console.Write(playerInBrazil.firstname);
Console.Write(" birthdate in UTC time is ");
Console.Write(playerInBrazil.birthdate);
Console.Write(" and in my local time is ");
//myTimeConvert =?
Console.WriteLine(myTimeConvert);
}
}
internal class Player
{
public ObjectId Id { get; set; }
public string firstname { get; set; }
public BsonDateTime birthdate { get; set; }
public string country { get; set; }
public double goals { get; set; }
}
}
BsonDateTime has a .ToLocalTime() method that returns a DateTime
More info here http://api.mongodb.com/csharp/current/html/M_MongoDB_Bson_BsonDateTime_ToLocalTime.htm
Related
I have an Entity MVC app with a code-first database. I need to produce a search box to search between 2 dates and return the records between those dates.
I will call the method with jQuery/ajax and render the results in a table.
I've tried writing an API, with no success. I am not even sure if this is the correct way to go about it?
namespace Areometrex_Leaflet.Models
{
[Table ("Flight_Lines")]
public class Flight_line
{
[Key]
public string Swath_name { get; set; }
public string Flight_name { get; set; }
public string Swath_record { get; set; }
public string Flight_date { get; set; }
public decimal Start_lat { get; set; }
public decimal Start_long { get; set; }
public decimal End_lat { get; set; }
public decimal End_long { get; set; }
public decimal Altitude { get; set; }
public DateTime Time_start { get; set; }
public DateTime Time_end { get; set; }
public string Sensor { get; set; }
}
public class FlightLineContext : DbContext
{
public DbSet<Flight_line> Flight_Lines { get; set; }
}
}
This is my model that holds the objects in the database. I need to search the "Flight_date" property, that is held in my DB in this following format as an "nvarchar" :
17/11/2018 11:09:18 PM
My current API looks something like this:
[HttpPost]
public IEnumerable<Flight_line> SearchFlight_Line()
{
string start, end;
var rc = RequestContext;
var data = rc.Url.Request.GetQueryNameValuePairs();
{
start = data.FirstOrDefault().Value ?? string.Empty;
end = data.LastOrDefault().Value ?? string.Empty;
}
//db format: 17/11/2018 11:22:56 PM
var s = DateTime.Parse(start);
var flightSearch = new List<Flight_line>();
using (_context)
{
var sql = $"SELECT * FROM Flight_Lines WHERE Flight_Date BETWEEN '{start}' AND '{end}'";
flightSearch = _context.Flight_Lines.SqlQuery(sql).ToList<Flight_line>();
}
return flightSearch;
}
Ideally, I want to call this API with jquery/Ajax and return results to be displayed in an MVC view. My guess is that this is dead easy, but I am only learning and I'm running out of ideas. I would have thought this was really simple, but I am struggling to find the answers I am looking for online, which leads me to believe perhaps I am doing it wrong?
First of all, don't save dates as string in your database, you will just have problems later on.
Instead of:
public string Flight_date { get; set; }
Set it up as DateTime:
public DateTime Flight_date { get; set; }
As far as the query for searching flights go, you can try this. This will return a list of "Flight_line" objects which you can then return wherever you need.
DateTime start = DateTime.Now;
DateTime end = DateTime.Now.AddDays(7);
var flights = _context.Flight_line.Where(f => f.Flight_date >= start && f.Flight_date <= end).ToList();
I'm using the code below in an attempt to Call TimeTree from Neo4jClient.
Other simple Calls work, but this one just does nothing. No errors, but also no new time object.
public class Trip
{
public long Id { get; set; }
public string Name { get; set; }
}
public class UUID
{
public long Value { get; set; }
}
public class TimeStamp
{
//public long Id { get; set; }
//public string Name { get; set; }
public long time { get; set; }
}
public class User
{
public long Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
class Program
{
static void Main(string[] args)
{
var client = new Neo4jClient.GraphClient(new Uri("http://localhost:7474/db/data"), "neo4j", "password");
client.Connect();
client.Cypher
.Match("(n)")
.DetachDelete("n")
.ExecuteWithoutResults();
var newUser = new User { Id = 456, Name = "Jim" };
client.Cypher
.Create("(user:User {newUser})")
.WithParam("newUser", newUser)
.ExecuteWithoutResults();
var newTrip = new Trip { Id = 001, Name = "Antibes" };
client.Cypher
.Match("(traveller:User)")
.Where((User traveller) => traveller.Id == 456)
.Create("(traveller)-[:TRAVELLING]->(travelling:Trip {newTrip})")
.WithParam("newTrip", newTrip)
.ExecuteWithoutResults();
var tstamp = client.Cypher
.Match("(trip:Trip)")
.Where((Trip trip) => trip.Name == "Antibes")
.With("trip AS tripToLink")
.Call("ga.timetree.events.attach({ node: 'tripToLink', time: 1483828451000, relationshipType: \"ARRIVING_ON\"})")
.Yield("node")
.Return(node => new { TimeStamp = node.As<TimeStamp>() });
The following does work in the Shell:
MATCH (trip:Trip)
WHERE trip.Name = "Antibes"
WITH trip
CALL ga.timetree.events.attach({node: trip, time: 1483828451000 , relationshipType: "ARRIVING_ON"})
YIELD node RETURN node
First off - good work on putting all the code there, it made life a lot easier!
I believe the problem here is two fold: the tstamp variable you have is of type: ICypherFluentQuery<???> (I'm using '?' to represent the anonymous type you're creating) - so you need to actually get the results to get any response. Until you call .Results you don't actually execute the query.
Typically, I like to create the query as you have and then execute after:
var tstamp = client.Cypher....
/* rest of the query here */
var tStampResults = tstamp.Results;
When you do this you'll probably get an error:
BadInputException: java.lang.String cannot be cast to org.neo4j.graphdb.Node
If you look at your response from the query you run in the console - you'll see you actually get back:
╒═══════════════════════════╕
│"node" │
╞═══════════════════════════╡
│{"Id":"1","Name":"Antibes"}│
└───────────────────────────┘
and that's because you are YIELDing node, so you'll only be able to cast to Trip type:
var query = client.Cypher
.Match("(trip:Trip)")
.Where((Trip trip) => trip.Name == "Antibes")
.With("trip")
.Call("ga.timetree.events.attach({node: trip, time: 1483828451000 , relationshipType: \"ARRIVING_ON\"})")
.Yield("node")
.Return(node => node.As<Trip>()); //<-- Change here
I'm facing an issue with date formatting. Upon calling up the UpdateItem action, the date format for CreatedAt gets messed up. I'm using JSON by the way, so must be something to do with date serialization.
Model:
public class Item
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public string CreatedBy { get; set; }
public DateTime? CreatedAt { get; set; }
public string UpdatedBy { get; set; }
public DateTime? UpdatedAt { get; set; }
}
Create action:
public int CreateItem(Item item)
{
var item = new Item();
viewModel.CopyToItem(item);
item.CreatedBy = WebSecurity.CurrentUserName;
item.CreatedAt = DateTime.Now;
db.Items.Add(item);
db.SaveChanges();
return item.ItemId;
}
Update action:
public void UpdateItem(Item item)
{
item.UpdatedBy = WebSecurity.CurrentUserName;
item.UpdatedAt = DateTime.Now;
db.SaveChanges();
}
The incorrect date format:
/Date(1395366469723)/
It should be:
2014-03-21T09:50:01.747
I tried this in the controller but get a String was not recognized as a valid DateTime' error.
string isoJson = JsonConvert.SerializeObject(DateTime.Now, new IsoDateTimeConverter());
item.CreatedAt = DateTime.ParseExact(isoJson, "yyyy-MM-dd hh:mm:ss.ttt", CultureInfo.InvariantCulture);
Using non-nullable DateTime in the model didn't fix it either.
Javascript uses Unix Time. If you are wanting to get a DateTime object with the given javascript date value, create a new DateTime object from 1/1/1970 and then add the milliseconds.
Observe:
var dt = new DateTime(1970, 1, 1).AddMilliseconds(1395366469723);
// "21/03/2014 1:47:49 AM"
I'm using c# driver to interact with mongoDB.
I have a class that I created and which I populate with the data I get from mongoDB.
One of the properties in that class is DateTime.
The value I get from mongo is /\Date(number)/. Which is ok because this is what I'm suppose to return to the client.
The value that I get from mongo after I retrieve the data is ISODate(some number).
I get an exception: "Invalid JSON primitive: ISODate".
How can I configure mongoDB to save the DateTime like I got it i.e. /\Date(number)/?
Sorry L.B - I didn't noticed your answer but went straight to the answer I was given.
Here's the class I'm trying to deserialize:
public class EventDate
{
public EventDate()
{
}
public int? VenueConfigID { get; set; }
public string Category { get; set; }
public DateTime DateAndTime { get; set; }
public string DisplayDate { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string ShortNote { get; set; }
public string Home { get; set; }
public int? ID { get; set; }
public string Name { get; set; }
}
Here's how I deserialize it:
mongo = MongoServer.Create();
mongo.Connect();
db = mongo.GetDatabase("productionDB");
var col = db.GetCollection<BsonDocument>("eventDates");
var query = Query<PerformerDates>.EQ(ev => ev.PerformerID, performerId);
//MongoCursor<BsonDocument> performer = col.Find(query);
MongoCursor<BsonDocument> performer = col.FindAll();
JavaScriptSerializer js = new JavaScriptSerializer();
List<EventDate> finalMatchedDates = new List<EventDate>();
foreach (var p in performer)
{
//System.Threading.Tasks.Task<EventDate[]> obj2 = JsonConvert.DeserializeObjectAsync<EventDate[]>(p.Elements.ToList()[3].Value.ToString());
EventDate[] obj3 = JsonConvert.DeserializeObject<EventDate[]>(p.Elements.ToList()[3].Value.ToString());
}
mongo.Disconnect();
Solved!!
Eventually I solved it. I used a string instead of a DateTime. When I get it from the DB, I convert it to a DateTime and when I sent it back to the client I serialize it with the format of: /\Date()/
Just use BsonSerializer.Deserialize method.
MongoDB's serializer has a much higher performance over NewtonSoft's Json.Net or Microsoft's DataContractSerializer.
Very common occurring problem! One solution is to use JSON.NET.
See this answer for more help. Although you might be confused with JSON DateTime object but don't worry. It will work!
string json; // Assign JSON here.
var v = Newtonsoft.Json.JsonConvert.DeserializeObjectAsync<T>(json);
I have some data coming back from a web service, which I have mapped to the following classes:
public class Webinar {
public string Title { get; set; }
public string Description { get; set; }
...
public List<TimeZone> TimeZones { get; set; }
}
public class TimeZone {
public TimeSpan GmtOffset { get; set; }
public List<Session> Session { get; set; }
}
public class Session {
public int WebinarKey { get; set; }
public DateTime StartTime { get; set; }
public TimeSpan Duration { get; set; }
}
Hopefully it's fairly clear what is going on: any one webinar can have multiple time zones which in turn holds the individual sessions.
I have a list of webinars List<Webinar> webinars = ... which is populated with data. On the page I would like to present webinars grouped by time zone (easy) and then sorted by their start time.
My problem: the sessions are not necessarily ordered by StartTime when I receive the data, which I would like to do. I have the following code which does work, but recreating each object and mapping out all it's properties is a PITA, is there a nicer way to do what I want?
List<Webinar> webinarsWithOrderedSessions = new List<Webinar>();
foreach (Webinar webinar in mappedWebinars)
{
Webinar currentWebinar = new Webinar
{
Title = webinar.Title,
...
TimeZones = new List<TimeZone>()
};
foreach (Webinar.TimeZone timeZone in webinar.TimeZones)
{
Webinar.TimeZone currentTimeZone = new TimeZone
{
Location = timeZone.Location,
Sessions = new List<Session>()
};
currentTimeZone.Sessions = timeZone.Sessions.OrderBy(session => session.StartTime).ToList();
currentWebinar.TimeZones.Add(currentTimeZone);
}
webinarsWithOrderedSessions.Add(currentWebinar);
}
UPDATE
Building upon the suggestion by #Max, why might this bit of code not work? It doesn't seem to add the sessions at all. I don't necessarily need two properties, so I thought I'd just apply your suggestion directly to the main property.
public class TimeZone
{
private List<Session> _sessions;
public List<Session> Sessions
{
get { return _sessions.OrderBy(s => s.StartTime).ToList(); }
set { _sessions = value; }
}
}
You can try with this:
public class TimeZone
{
private List<Session> _ordered;
public TimeSpan GmtOffset { get; set; }
public List<Session> Session
{
get
{
return this._ordered;
}
set
{
if (value != null)
{
this._ordered = value.OrderBy(p => p.StartTime);
}
}
}
}
I has improved the answer using explicit set and get
Try this way:
var webinarsWithOrderedSessions = (from x in mappedWebinars
from y in x.TimeZones
from s in y.Session
orderby s.StartTime
select x).ToList();