This has been giving me trouble for a long time now, and I wouldn't think this would be so hard. I have a model with some dates, and date data coming from the API like so:
{
...
tollgate1: '2016-04-15',
tollgate2: '2017-01-01',
projectClose: '2016-10-21',
}
I created a format-date helper (which uses moment.js) to format the dates in view mode, like so:
And that's shows it correctly. However, when I switch to edit mode, the input elements are still referencing the same values, but now they all go one day earlier!
This has been maddening for some time. I've thought it might be due to a like of time zone information in the data, but since I can't change the data that's fed to my app, how can I get it to just display the date in the data, regardless of timezone? For example, with the Tollgate 1 date, I would want it to show April 15 no matter where the user is in the world.
Okay, so as with many things, this isn't an Ember thing so much as just a JavaScript thing. It's really hard learning both at once!
Since my dates coming down from the API don't have a time zone, they're assumed to be GMT, and so my EST timezone of -4 hours makes it show as the day before. Apparently moment.js has some built-in handling so that's why the format-date helper works fine.
What I did to solve is to just add computed properties on my model for each date, and create a new Date object by pulling out the parts from the input date, like so:
function convertDateToUtc(d) {
if(d) {
return new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
} else {
return null;
}
}
export default DS.Model.extend({
...
tollgate1Date: Ember.computed('tollgate1', function() {
return convertDateToUtc(this.get('tollgate1'));
})
});
Related
I have a component, p-Calendar.
I had no trouble finding a way to receive the date I selected, and modify it.
<p-calendar
[showIcon]="true"
(onSelect)="onSelectMethod($event)"
[(ngModel)]="myDate"
[dataType]="date"
>
</p-calendar>
So basically when I hit a different date in the calendar, it does catch the date correctly. It will transfer this information:
"Thu Dec 08 2016 00:00:00 GMT-0500 (Eastern Standard Time)"
While I can see that all this detail is useful, I really just want my component to receive:
12/08/16.
Is there any simple way to do this, perhaps some inherent method that comes with the calendar, without manually doing string modifications in my code? I read the documentation and couldn't find the information I am looking for.
The onBlur method seems to be transferring the data in the way I want it to. Unfortunately onBlur only works when you type in the date manually, or when you're one date selection behind. It would be great to somehow call PrimeNG's onBlur method after you made a selection in the calendar drop-down.
I wouldn't particularly recommend this as it's a hacky solution, it is probably better to do transformations of the myDate as appropriate for display or other purposes.
If you really, really want to do this so that the myDate in your component only contains a short date without all that time and location information you can go ahead and separate out the model bindings to make it work like so:
template.html
<p-calendar [ngModel]="myDate"
(onSelect)="onSelectMethod($event)"
[dataType]="date">
</p-calendar>
component.ts
onSelectMethod(event) {
let d = new Date(Date.parse(event));
this.myDate = `${d.getMonth()+1}/${d.getDate()}/${d.getFullYear()}`;
}
Here's a functioning demo: http://plnkr.co/edit/IGRfXjtqIo0TEr2iDC06?p=preview
In case you were wondering about applying a pipe, you would do a straight [(ngModel)]="myDate" bind and, where you want to see the short date in the template do {{myDate | date: 'MM/dd/yy'}}
I'm currently working with embarcadero c++, this is the first time I'm working with it so it's completely new to me.
What I'm trying to achieve is to get the current date, make sure the date has the "dd/MM/yyyy" format. When I'm sure this is the case I want to add a month to the current date.
So let's say the current date is 08/18/2016 this has to be changed to 18/08/2016 and then the end result should be 18/09/2016.
I've found that there is a method for this in embarcardero however I'm not sure how to use this.
currently I've only been able to get the current date like this.
TDateTime currentDate = Date();
I hope someone will be able to help me out here.
I figured it out.
After I've searched some more I found the way to use the IncMonth method on this page.
The example given my problem is as follows:
void __fastcall TForm1::edtMonthsExit(TObject *Sender)
{
TDateTime StartDate = edtStartDate->Text;
int Months = edtMonths->Text.ToInt();
TDateTime NextPeriod = IncMonth(StartDate, Months);
edtNextPeriod->Text = NextPeriod;
}
After looking at I changed my code accordingly to this
TDateTime CurrentDate = Date();
TDateTime EndDate = IncMonth(CurrentDate, 1);
A date object doesn't have a format like "dd/MM/yyyy". A date object is internally simply represented as a number (or possibly some other form of representation that really isn't your problem or responsibility).
So you don't have to check if it's in this format because no date objects will ever be in this format, they simply don't have a format.
You will have to do additions/subtractions on the Date object that the language or library gives you, THEN (optionally) you can format it to a human-readable string so it looks like 18/08/2016 or 18th of August 2016 or whatever other readable format that you choose.
It might be that the TRANSFER of a date between 2 systems is in a similar format, but then formatting the date like that is entirely up to you.
As for how to do that, the link you posted seems like a possible way (or alternatively http://docwiki.embarcadero.com/Libraries/Berlin/en/System.SysUtils.IncMonth), I'm afraid I can't give you an example as I'm not familiar with the tool/language involved, I'm just speaking generically about Date manipulations and they should ALWAYS be on the raw object.
I make a simple domain class
class Meetings {
Date when
String where
}
Then I run 'generate-all' on Meetings. I then start the app 'RunApp'.
In the app I'm able to to choose the month, day, and year for the when variable, however I can't choose the time as in hours:minutes (example 7:30). I wouldn't expect to be able to do this, but if I save the date it formats it as month, day, year, and then -00:00:00. How do I set the time using the date variable? or is there another way?
If you are using the datepicker tag in grails, it is pretty straight forward.
In the views folder under a domain class folder there is _form.gsp. Inside _form.gsp is a date picker tag.
<g:datePicker name="dateTimeVariableName" value="${dateTimeValue}"
default="${new Date().clearTime()}" precision="minute"/>
The keyword here is precision.
You should check the documentation. Its always a good idea. Hope this helps.
I'm working on an app that allows the user to edit several dates in a form. The dates are rendered in the European format (DD-MM-YYYY) while the databases uses the default YYYY-MM-DD format.
There are several ways to encode/decode this data back and forth from the database to the user, but they all require a lot of code:
Use a helper function to convert the date before saving and after retrieving (very cumbersome, requires much code)
Create a separate attribute for each date attribute, and use the setNameAttribute and getNameAttribute methods to decode/encode (also cumbersome and ugly, requires extra translations/rules for each attribute)
Use JavaScript to convert the dates when loading and submitting the form (not very reliable)
So what's the most efficient way to store, retrieve and validate dates and times from the user?
At some point, you have to convert the date from the view format to the database format. As you mentioned, there are a number of places to do this, basically choosing between the back-end or the front-end.
I do the conversion at the client side (front-end) using javascript (you can use http://momentjs.com to help with this). The reason is that you may need different formats depending on the locale the client is using (set in the browser or in his profile preferences for example). Doing the format conversion in the front-end allows you to convert to these different date formats easily.
Another advantage is that you can then use the protected $dates property in your model to have Laravel handle (get and set) these dates automatically as a Carbon object, without the need for you to do this (see https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Model.php#L126).
As for validation, you need can then use Laravel's built-in validation rules for dates, like this:
'date' => 'required|date|date_format:Y-n-j'
While client-side is good for UX, it doesn't let you be sure, all will be good.
At some point you will need server-side validation/convertion anyway.
But here's the thing, it's as easy as this:
// after making sure it's valid date in your format
// $dateInput = '21-02-2014'
$dateLocale = DateTime::createFromFormat('d-m-Y', $dateInput);
// or providing users timezone
$dateLocale =
DateTime::createFromFormat('d-m-Y', $dateInput, new DateTime('Europe/London'));
$dateToSave = $dateLocale
// ->setTimeZone(new TimeZone('UTC')) if necessary
->format('Y-m-d');
et voila!
Obviously, you can use brilliant Carbon to make it even easier:
$dateToSave = Carbon::createFromFormat('d-m-Y', $dateInput, 'Europe/London')
->tz('UTC')
->toDateString(); // '2014-02-21'
Validation
You say that Carbon throws exception if provided with wrong input. Of course, but here's what you need to validate the date:
'regex:/\d{1,2}-\d{1,2}-\d{4}/|date_format:d-m-Y'
// accepts 1-2-2014, 01-02-2014
// doesn't accept 01-02-14
This regex part is necessary, if you wish to make sure year part is 4digit, since PHP would consider date 01-02-14 valid, despite using Y format character (making year = 0014).
The best way I found is overriding the fromDateTime from Eloquent.
class ExtendedEloquent extends Eloquent {
public function fromDateTime($value)
{
// If the value is in simple day, month, year format, we will format it using that setup.
// To keep using Eloquent's original fromDateTime method, we'll convert the date to timestamp,
// because Eloquent already handle timestamp.
if (preg_match('/^(\d{2})\/(\d{2})\/(\d{4})$/', $value)) {
$value = Carbon\Carbon::createFromFormat('d/m/Y', $value)
->startOfDay()
->getTimestamp();
}
return parent::fromDateTime($value);
}
}
I'm new in PHP, so I don't know if it's the best approach.
Hope it helps.
Edit:
Of course, remember to set all your dates properties in dates inside your model. eg:
protected $dates = array('IssueDate', 'SomeDate');
With DateJS, you'd add e.g. six months to the current date like this:
Date.today().addMonths(6);
However, I need to add 24 months not to today's date, but to a date which a user has typed into a date field. So the today() should in principle be replaced by something like this.getField('begin_date').value.
The result shall be written into another data form field.
I tried hard, but couldn't make it. Can anyone help me out?
Providing the input value is a textual representation of a date, you need to convert it into a Date object at the first place. Then you can work with it as you want.
DateJS has a pretty smart parse() function which does exactly that, so you'd achieve it like this:
Date.parse(this.getField('begin_date').value).addMonths(24)
When a specific date format is needed, like DD.MM.YYYY commonly used in Europe, you can use parseExact() and specify the format. Like this:
Date.parseExact(dateToParse, 'dd.MM.yyyy') // leading zeroes required; parses 01.04.2014 but not 1.4.2014
Date.parseExact(dateToParse, 'd.M.yyyy') // leading zeroes not required; parses both 01.04.2014 and 1.4.2014
Here is a solution that I found for my problem, using DateJS as well:
start = this.getField('begin_date').value;
var d1 = util.scand("dd.mm.yyyy", start);
var myDate = new Date(d1);
result = myDate.addMonths(24);
This works pretty fine, also spanning leap years, except for the 28th of February, 2014/2018/2022 ... ; the result then will be the 28th of February, 2016/2020/2024 ... and not the 29th of February 2016/2020/2024... In these cases it's up to the user to accept the 28th or to manually change the date to the 29th.