1

I'd like to start by stating I have very little experience with Angular as this is the first project I've worked on that uses it.

Within the controller I make an AJAX call which returns a json. One of the json objects is minutes in the following format: 1385

I'd like to convert this number into something like this: 8d 15h 0m using an Angular filter

Im wondering how this would be possible?

Rohan Büchner
  • 5,333
  • 4
  • 62
  • 106
Ryan Wright
  • 13
  • 1
  • 4

3 Answers3

2

Answer

Yes. It is 100% possible. Create a filter like below and add your specific date calculation inside the filter.

How to do the date calculation:

In terms of the actual date calculation, it will be nothing more than regular JavaScript logic. Here you have a few options:

  • The native Date() object will expose various .getSomething() functions
  • MomentJS is also good, as its a library designed for these things specifically
  • Manual calculation

If you'd like to know how to do this manually. Conceptually the calculation is something like below... the idea is, a rolling calculation where you get the higher time unit, then keep subtracting it from the next calculation, carrying the leftover time along.

Input = Original Minute value     
Days = Input / 60 [mins in an hour] / 24 [total hours in day]  
Hours = Leftover / 60 [mins in an hour] 
Mins = Leftover

A quick search on SO yielded this solution for a custom calculation of sorts. I used the linked calculation on my sample below.

Example

var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {})
  .filter('myDateFilter', ['$filter',
    function($filter) {
      return function(input) {

        // set minutes to seconds
        var seconds = input * 60

        // calculate (and subtract) whole days
        var days = Math.floor(seconds / 86400);
        seconds -= days * 86400;

        // calculate (and subtract) whole hours
        var hours = Math.floor(seconds / 3600) % 24;
        seconds -= hours * 3600;

        // calculate (and subtract) whole minutes
        var minutes = Math.floor(seconds / 60) % 60;

        return days + 'd ' + hours + 'h ' + minutes + 'm ';
      }
    }
  ]);
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
</head>

<body ng-controller="MainCtrl">

  1385 minutes = {{ 1385 | myDateFilter }}

</body>

</html>
Rohan Büchner
  • 5,333
  • 4
  • 62
  • 106
1

I suggest a slightly shorter version as an alternative, that uses new Date() object and gets its components individually with predefined methods. It works the same way and uses less computations.

Here is a demo:

var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {});
app.filter('myDateFilter', ['$filter',
  function($filter) {
    return function(input) {
      var inp = new Date(0, 0, 0, 0, input, 0); // assumes minutes as an input
      var m = inp.getMinutes();
      var h = inp.getHours();
      var d = inp.getDay();

      return d + 'd ' + h + 'h ' + m + 'm ';
    }
  }
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>

<div ng-app="app" ng-controller="MainCtrl">
  1385 minutes = {{ 1385 | myDateFilter }}
</div>
Aleksey Solovey
  • 4,153
  • 3
  • 15
  • 34
1

Here is a pipe you can copy/paste for angular 6+. I made it a bit more robust too:

import { Pipe, PipeTransform } from '@angular/core';

/**
 * Format a value in minutes as [x(d| days)] y(h| hours) z(m| minutes)
 *
 * Usage:
 *  value | hoursMinutes // 0d 3h 20m
 *  value | hoursMinutes: 'long':false // 3 hours 20 minutes
 */
@Pipe({
  name: 'hoursMinutes'
})
export class HoursMinutesPipe implements PipeTransform {
  transform(minutes: number, format = 'short', includeDays = true): any {
    let formatted = '';
    // set minutes to seconds
    let seconds = minutes * 60;

    // calculate (and subtract) whole days
    let days = 0;
    if (includeDays) {
      days = Math.floor(seconds / 86400);
      seconds -= days * 86400;
      formatted = `${days}d `;
    }

    // calculate (and subtract) whole hours
    const hours = Math.floor(seconds / 3600) % 24;
    seconds -= hours * 3600;

    // calculate (and subtract) whole minutes
    const min = Math.floor(seconds / 60) % 60;

    formatted += `${hours}h ${min}m`;

    if ('long' === format) {
      formatted = formatted.replace('d', ' days');
      formatted = formatted.replace('h', ' hours');
      formatted = formatted.replace('m', ' minutes');
    }

    return formatted;
  }
}
rynop
  • 50,086
  • 26
  • 101
  • 112