1

I'm a bit newbie with the MS tech stack, I developed a REST API using c# and EF core

I have this body request

{
  "name": "Test Fecha",
  "awardDate": "2020-05-19T00:00:00.000Z",
  "governancePermit": "TEST",
  "totalTickets": 5000,
  "legals": "TEST",
  "logo": "TEST",
  "ticket": "TEST",
  "ticketLifeTime": "200000",
  "ticketPrice": 2000,
  "saleStartDate": "2020-05-19T00:00:00.000Z",
  "saleEndDate": "2020-05-19T00:00:00.000Z"
}

Thats the body of a post request to create a new resourse. That body is procesed by the next code:

Controller:

[HttpPost("/api/contest")]
public async Task<IActionResult> Create([FromBody] ContestCreateRequest request)
{

    var activeContest = await _contestService.GetByStatus("Active");
    if (activeContest == null)
    {
        var contest = new Contest
        {
            Name = request.Name,
            AwardDate = DateTime.Parse(request.AwardDate),
            TotalTickets = request.TotalTickets,
            GovernancePermit = request.GovernancePermit,
            Logo = request.Logo,
            Ticket = request.Ticket,
            Legals = request.Legals,
            Status = "Active",
            TicketLifeTime = request.TicketLifeTime,
            TicketPrice = request.TicketPrice,
            SaleStartDate = DateTime.Parse(request.SaleStartDate),
            SaleEndDate = DateTime.Parse(request.SaleEndDate),
            CreatedAt = DateTime.Parse(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")),
            UpdatedAt = DateTime.Parse(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")),
        };

        var result = await _contestService.Create(contest);
        if (result)
        {
            var response = new GeneralResponse
            {
                Message = "Contest Create",
                Data = null,
                Status = 201,
                Success = true
            };

            return Ok(response);
        }
        else
        {
            var response = new GeneralResponse
            {
                Message = "Contest not create",
                Data = null,
                Status = 400,
                Success = false
            };

            return BadRequest(response);

        }
    }
    else
    {
        var response = new GeneralResponse
        {
            Message = "Only one contest can be active",
            Data = null,
            Status = 400,
            Success = false
        };

        return BadRequest(response);
    }

}

As you can see I am only parsing the dates from string to a DateTime Object

Then the the object(entity) is inserted in the data base with the following code:

public async Task<bool> Create(Contest contest)
{
    await _dataContext.Contest.AddAsync(contest);
    var create = await _dataContext.SaveChangesAsync();
    return create > 0;
}

Model:

[Table("Contest")]
public class Contest
{
    [Key]
    public int ContestId { get; set; }
    [Column("id_udlap")]
    public int IdUdlap { get; set; }
    [Column("name")]
    public string Name { get; set; }
    [Column("start_date")]
    public DateTime StartDate { get; set; }
    [Column("end_date")]
    public DateTime EndDate { get; set; }
    [Column("award_date")]
    public DateTime AwardDate { get; set; }
    [Column("avaible_tickets")]
    public int AvaibleTickets { get; set; }
    [Column("total_tickets")]
    public int TotalTickets { get; set; }
    [Column("status")]
    public string Status { get; set; }
    [Column("dynimic_fields")]
    public string DynamycFields { get; set; }
    [Column("custom_message")]
    public string CustomMessage { get; set; }
    [Column("grateful_message")]
    public string GratefulMessage { get; set; }
    [Column("ticket_life_time")]
    public string TicketLifeTime { get; set; }
    [Column("ticket_price")]
    public double TicketPrice { get; set; }
    [Column("governance_permit")]
    public string GovernancePermit { get; set; }
    [Column("legals")]
    public string Legals { get; set; }
    [Column("logo")]
    public string Logo { get; set; }
    [Column("ticket")]
    public string Ticket { get; set; }
    [Column("sale_start_date")]
    public DateTime SaleStartDate { get; set; }
    [Column("sale_end_date")]
    public DateTime SaleEndDate { get; set; }
    [Column("created_at")]
    public DateTime CreatedAt { get; set; }
    [Column("updated_at")]
    public DateTime UpdatedAt { get; set; }

    public List<Ticket> Tickets { get; set; }



    public Contest() {}
}

But when I retrieve the object with this code:

public async Task<Contest> GetByStatus(string status)
{
    var result = await _dataContext.Contest.SingleOrDefaultAsync(c => c.Status == status);
    return result;
}

In this case status is "Active", that returns this.

{
  "status": 200,
  "message": "Active Contest",
  "data": {
    "contestId": 1,
    "name": "Test Fecha",
    "startDate": "0001-01-01T00:00:00",
    "endDate": "0001-01-01T00:00:00",
    "awardDate": "2020-05-18T19:00:00",
    "avaibleTickets": 0,
    "totalTickets": 5000,
    "status": "Active",
    "dynamycFields": null,
    "customMessage": null,
    "gratefulMessage": null,
    "ticketLifeTime": "200000",
    "ticketPrice": 2000,
    "governancePermit": "TEST",
    "legals": "TEST",
    "logo": "TEST",
    "ticket": "TEST",
    "saleStartDate": "2020-05-18T19:00:00",
    "saleEndDate": "2020-05-18T19:00:00",
    "createdAt": "2020-05-19T19:04:10.517",
    "updatedAt": "2020-05-19T19:04:10.518",
    "tickets": null
  },
  "success": true,
  "pages": 0,
  "totalData": 0
}

This three fields (saleEndDate,saleEndDate,awardDate) are not the value that I charge in the request body.

The fast solution is add the hours that are out of phase, but Why this is happen? Is there other way to fix it or avoid it.

I suspect that is a SQL server configuration issue because I did it with two different instances and I obtain two different results, but I am not sure

Thanks a lot.

  • What timezone is your computer in? – Caius Jard May 20 '20 at 00:42
  • Incidentally, did you realize that `CreatedAt = DateTime.Parse(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")),` should probably just be `CreatedAt = DateTime.UtcNow,` ? And did C# really not parse the saleXXXDate datetime for you? – Caius Jard May 20 '20 at 00:44
  • Mi computer is in (GMT-5), And I parced the created at, because the Front-End developer asked for, I think is because in JS is easier manege date in that format, I use Consolo.WriteLine to print the atributes of the object and are correct before insert them into th DB – Alan Garduño III May 20 '20 at 01:09
  • So, did you notice that your computer is in -5 and the date that comes out the db and the date in the incoming json is 5 hours apart? – Caius Jard May 20 '20 at 01:13
  • Yes, I also think its about "locale time" issue but I don't really know why, I was supposing that wherever I store in DB will be the same when I retrieve the information, Can I fix that difference with code or the only way is adding the time that was "stolen" by the local time? – Alan Garduño III May 20 '20 at 01:20
  • I don't think it's stolen per se; it's jsut that the datettimes you're looking at now are local ones, whereas the ones in the db are UTC ones.. midnight 00:00 on the 19th may is the same moment as 19:00 on the 18th of may, for a person in -5. I'm in UTC, you're in -5. My clock now says 00:00, yours says 19:00.. – Caius Jard May 20 '20 at 01:22
  • I just notice by debugging a little deep that Date.Parse() is no working well, it's weird because in the in the deployment in a azure app service this work – Alan Garduño III May 20 '20 at 01:23
  • 1
    Azure machines live in UTC. Everyone should always work in UTC. Actually, we should discard all the timezones in the world, because theyre a crazy idea. It would be easier for people in different parts of the world to just get used to the idea that "I'm in -2. when the clock says 7, i go to work, just like all the people in +1 go to work when it says 10 on their clock".. Coutries are already throwing away the idea of daylight savings.. we just need to go that one step further and ditch timezones too :) – Caius Jard May 20 '20 at 01:25

1 Answers1

2

With the comments of Caius Jard (thanks a lot) and this question in SO Convert DateTimeOffset to DateTime and add offset to this DateTime And this: Convert datetime without timezone

I was able to achieve the desired behavior

Hera the code that works for me:

 var activeContest = await _contestService.GetByStatus("Active");
            if (activeContest == null)
            {   
                var AwardDateFormated = DateTimeOffset.Parse(request.AwardDate);
                var StartDateFormated = DateTimeOffset.Parse(request.SaleStartDate);
                var EndDateFormated = DateTimeOffset.Parse(request.SaleEndDate);
                var contest = new Contest
                {
                    Name = request.Name,
                    AwardDate = AwardDateFormated.UtcDateTime,
                    TotalTickets = request.TotalTickets,
                    GovernancePermit = request.GovernancePermit,
                    Logo = request.Logo,
                    Ticket = request.Ticket,
                    Legals = request.Legals,
                    Status = "Active",
                    TicketLifeTime = request.TicketLifeTime,
                    TicketPrice = request.TicketPrice,
                    SaleStartDate = StartDateFormated.UtcDateTime,
                    SaleEndDate = EndDateFormated.UtcDateTime,
                    CreatedAt = DateTime.Parse(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")),
                    UpdatedAt = DateTime.Parse(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")),
                };
                var result = await _contestService.Create(contest);

Now I retrieve exactly the data that I want, I don't really know if this is the best solution but for now works. Hope helps someone else.