I have a question about the library moments.js, I have an application in angularjs where I have six select elements for the year, month, day, hour, minutes, and am / pm format. I am using the following format moment to build m.format date ('YYYY-MM-DD hh: mm: ss a).
The code is as follows:
var m = moment([scope.val.year, scope.val.month, scope.val.date, scope.val.hour, scope.val.minute]); //build date
model.$setViewValue(m.format('YYYY-MM-DD hh:mm:ss a'))
I get the data m.hour ()
, m.minute ()
, etc but there is a way to get the am / pm format, I have not found anything about it, something perhaps as m.meridian () => "am "or" pm "
.
I would build the array passing as parameter if am or pm, and then also would get from any date if am or pm date.
You could also do something like m.format('a')
The other answer is very good. It helped me to create my demo because with-out it I would have missed the point with the month (0 to 11).
But you don't need to create the meridiem function because it's already implemented in moment.js
. The point is that the usage is not very clear from the docs.
You can use the meridiem
function like this:
var curDate = moment().hour(yourHour); // create a moment date with the hour you'd like to test
var meridiem = curDate
.localeData().meridiem(hour); // will return AM/PM String
If you need a boolean instead of AM/PM
string you can pass the AM/PM string to curDate.localeData().isPM(meridiem)
. That will return true or false.
The point with the month that you don't want to display 0 to 11 in your select can be fixed by a displayLabel
function that will increment every value of the month array. Then you'll have it displayed 1 to 12 but stored as 0 to 11. If you're writing a directive that could be better handled by a $parser / $formatter
function of ngModel
.
Please have a look at the demo below or at this jsfiddle.
angular.module('demoApp', [])
.filter('momentDate', MomentDateFilter)
.filter('momentUTC', MomentUTCFilter)
.controller('MainController', MainController);
function MomentDateFilter() {
return function(input, format) {
return moment(input).format(format);
};
}
function MomentUTCFilter() {
return function(input, format) {
return moment.utc(input).format(format);
};
}
function MainController($scope, $log) {
var vm = this,
now = moment();
vm.checkHour = checkHour;
vm.dateSelect = dateSelection();
vm.displayLabel = displayLabel;
vm.now = now;
vm.selected = {
"day": 27,
"month": 8,
"year": 2015,
"hour": 18,
"meridiem": "PM",
"minutes": 6,
"seconds": 20
};
function dateSelection() {
return { // generated on every page load for demo
// better store the generate object as json and load it
day: createRange(1,31),
month: createRange(0,11),
year: createRange(1900, 2100),
hour: createRange(0,24),
minutes: createRange(0,59),
seconds: createRange(0,59),
meridiem: 'AM_PM'.split('_')
};
}
function displayLabel(key, value) {
if (key === 'month') {
value++; // increment month for correct month value 1 to 12
}
return value;
}
function checkHour(key, hour) { // updates meridiem (AM/PM)
if (key === 'hour') {
var curDate = moment().hour(hour);
//console.log('check hour', hour, curDate.hour(), curDate.localeData());
vm.selected.meridiem = curDate
.localeData().meridiem(hour);
//console.log(curDate
// .localeData().isPM(vm.selected.meridiem));
}
//console.log('changed', key);
}
//console.log(this.dateSelect);
function createRange(from, to) {
var arr = [];
for(i=from; i<=to; i++) {
arr.push(i);
}
//console.log(arr);
return arr;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.0/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.js"></script>
<div ng-app="demoApp" ng-controller="MainController as mainCtrl" class="container-fluid">
<form class="form-inline">
<div ng-repeat="(key, array) in mainCtrl.dateSelect" class="form-group">
<label>{{key}}</label><select class="form-control" ng-change="mainCtrl.checkHour(key, array[mainCtrl.selected[key]])" ng-model="mainCtrl.selected[key]" ng-options="value as mainCtrl.displayLabel(key, value) for value in mainCtrl.dateSelect[key]" ng-disabled="key === 'meridiem'">
</select>
</div>
</form>
selected: <pre>{{mainCtrl.selected|json}}</pre>
raw date (unformatted, UTC): {{mainCtrl.selected | momentUTC}}<br/>
date formatted (meridiem locale): {{mainCtrl.selected | momentUTC : 'LLLL' }}<br/>
now (momentjs) {{mainCtrl.now}}
</div>
You can extend the moment with the following function and use it in the same style as you set & get hour, day, minute etc..
moment.fn.meridiem = function(newMeridiem) {
if (!newMeridiem) {
return this.format('A'); // or `return this.hours() < 12 ? 'AM' : 'PM';`
}
if (newMeridiem.toUpperCase() === 'AM' && this.hours() > 12) {
this.hours(this.hours() - 12);
} else if (newMeridiem.toUpperCase() === 'PM' && this.hours() <= 12) {
this.hours(this.hours() + 12);
}
return this;
}
console.log("Current:",moment().meridiem());
console.log("Set as am result:",moment().meridiem('am').meridiem());
console.log("Set as pm result:",moment().meridiem('pm').meridiem());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js"></script>
Copied from https://github.com/moment/moment/issues/3873