How to get the Meridian (am / pm) with moments and angular

I have a question about .js library moments, I have an application in angularjs where I have six select elements for the format year, month, day, hour, minutes and am / pm. I use the following format to create the 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 format am / pm, I did not find anything about it, perhaps like m.meridian () => "am "or" pm " .

I would build an array passing as a parameter if am or pm, and then also get from any date if am or pm date.

+5
source share
3 answers

A few things:

  • The word you are looking for is meridiem , not meridian . This is a Latin word meaning "mid day". The Corresponding Member is “ante meridiem” (until midday) and PM is “post meridiem” (after midday).

  • The .hours() function and the input array passed to the moment constructor expect a 24-hour clock, from 0 to 23. There is no built-in function to receive or output a 12-hour clock or meridium (am / pm).

  • The parsing and formatting functions at the moment have options for the 12-hour clock ( h or hh ) and meridiem ( A or A ), but you do not parse or parse the formatting in your use case, so they will be a little awkward to use. In particular, they are based on the current settings of the current locale, so string testing will be problematic if the locale was not tied to a specific language.

  • You can use these simple functions to convert from 12-hour + meridium to 24 hours and vice versa. They are independent of the moment, so you can also use them with a Date object or elsewhere.

     function hours12to24(h, pm) { return h == 12 ? pm ? 12 : 0 : pm ? h + 12 : h; } function hours24to12(h) { return { hour : (h + 11) % 12 + 1, pm : h >= 12 } } 

    To test these features:

     function test() { for (var i = 0; i <= 23; i++) { var x = hours24to12(i); var h = hours12to24(x.hour, x.pm); console.log(i + " == " + x.hour + (x.pm ? " pm" : " am") + " == " + h); } } 
  • Also, be careful when calling .month() to get the month number, the results are 0-11, not 1-12. The same is true when building an input array. You need to use 0-11 in the drop-down list, or you need to add or subtract 1 accordingly.

+6
source

You can also do something like m.format('a')

+6
source

The other answer is very good. This helped me create a demo, because without it I would have missed this moment with a month (from 0 to 11).

But you do not need to create the meridiem function, because it is already implemented in moment.js . The fact is that the use of documents is not very clear from the documents.

You can use the meridiem function as follows:

 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 want a boolean string instead of the string AM/PM , you can pass the string AM / PM to curDate.localeData().isPM(meridiem) . This will return true or false.

A point with a month that you do not want to display from 0 to 11 in your chosen one can be fixed using the displayLabel function, which will increase each value of the month array. Then you will see that it is displayed from 1 to 12, but saved as from 0 to 11. If you write a directive that can be better handled by the $parser / $formatter ngModel .

Please see the demo below or on 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> 
+1
source

Source: https://habr.com/ru/post/1232373/


All Articles