How to humanize duration in angularjs? - javascript

I am using momentjs and moment-duration-format to show duration in Y M D HH:mm:ss format depending on duration if it includes year, month, day, hour, minutes & seconds, with ngTable sorting and filter on this field.
Code
$scope.getTableDataDuration = function(item) {
if (angular.isDefined(item) && item != null) {
var tmp = "";
if (item > 31536000) { //year
tmp = moment.duration(item, "year").format("Y M D h:mm:s");
return tmp;
} else if (item > 2628000) { //month
tmp = moment.duration(item, "month").format("M D h:mm:s");
return tmp;
} else if (item >= 86400) { //day
tmp = moment.duration(item, "days").format("D h:mm:s");
return tmp;
} else if (item < 60) {
return item;
} else if (item < 3600) { //minute
tmp = moment.duration(item, "minutes").format("h:mm:s");
return tmp;
}
}
return;
}
Plunker link
Update
So for example:
duration in seconds 331 should show 05:51
duration in seconds 7245 should show 02:01:25
similarly till years
Given a duration, I need to humanize it similar to above example

I believe that you misunderstood the documentation. I did not use moment-duration personally, but from the documentation on GitHub it seems that what you want to use is this
moment.duration(99544, "seconds").format("D h:mm:s");
It informs the Duration plugin, that the input number is in seconds, which it is. And then you format it via the provided format string.
See this example https://github.com/jsmreese/moment-duration-format#weeks
Here he uses moment.duration(123, "days").format("w W", 2); which basically says "I have 123 days and I want to convert it to number of weeks"

Related

Best way to normalize time in JS

I have some data that's inconsistent. It's all time related but I have some records that shows 3pm others 14:00.
Is there an easy way to normalize that in JS?
Thanks
This function will return you a 24-hour-formatted time
function normaliseTime(time) {
// If there is AM/PM in the string, do conversion
if (time.toUpperCase().indexOf('M') >= 0) {
// Remove the AM/PM text and split the hour and minute
var tmArray = time.replace(/\D/g, '').split(':');
// If PM, add 12 to the hour
if (time.toUpperCase().indexOf('PM') >= 0) {
tmArray[0] = parseInt(tmArray[0]) + 12;
}
// If minutes were not provided (i.e., 3PM), add 00 as minutes
if (tmArray.length < 2) {
tmArray[1] = '00';
}
return tmArray.join(':');
}
// If there was no AM/PM in the input, return it as is
return time;
}

Best way to get prior value from today

I am working on requirement and need to check about my logic that I have implemented. Please help.
I want to get the 1 month,3 month and 6 month return % of stock price from current date.
I have a table which have date and price array field as shown.
{
"_id" : ObjectId("5a65d0e7bfd103df081a75a8"),
"aId" : 93,
"values" : [
{
"date" : "2018-02-06",
"Price" : 27.9057
},
{
"date" : "2018-02-05",
"Price" : 28.0406
}
]
}
My logic
Iterate through the date,price array and pass the date to a function which will calculate days difference.
function differenceFromTodayInDays(FromDate) {
var currentDate = new Date();
var previousDate = new Date(FromDate);
var difference = Math.floor(currentDate.getTime() - previousDate.getTime());
var secs = Math.floor(difference / 1000);
var mins = Math.floor(secs / 60);
var hours = Math.floor(mins / 60);
var days = Math.floor(hours / 24);
return days;
}
Push the days into different arrays if days = 30,31 or 60,61 or 91,90,92,93
if (differenceInDays == 30 || differenceInDays == 31) {
$scope.days30.push(index);
so overall till now
$scope.timeDiffInDays = function(index, otherDate) {
$scope.days30 = [];
var differenceInDays = differenceFromTodayInDays(otherDate);
if (differenceInDays == 30 || differenceInDays == 31) {
$scope.days30.push(index);
}
}
Here I have index and can take the price value of that index and calculate return % from current value.
My Concerns are
Values in array are increasing daily and it will slow down process.
Date Difference of 30/31/60/61/90/91 is not available sometimes as some days are holidays and those values are not there in array.so it is hard to get return %.
I am looking for some efficient logic for this.
Thanks,
J
If I understand correctly why you are including date part in your code? Get month and year only and write a code like (endyear-startyear)*12+(endmonth-startmonth)- (enddate>=startdate?0:1).
I don't have laptop support now(writing from phone). I think getMonth() and getFullYear() will help you to do this

Working Days Javascript with Extra Dates

I have a function which calculates a date that is passed and adds a given number of days to the result ensuring the outputted date doesn't fall on a weekend.
The function
function addWorkingDays(datStartDate, lngNumberOfWorkingDays, blnIncSat, blnIncSun) {
var intWorkingDays = 5;
var intNonWorkingDays = 2;
var intStartDay = datStartDate.getDay(); // 0=Sunday ... 6=Saturday
var intOffset;
var intModifier = 0;
if (blnIncSat) { intWorkingDays++; intNonWorkingDays--; }
if (blnIncSun) { intWorkingDays++; intNonWorkingDays--; }
var newDate = new Date(datStartDate)
if (lngNumberOfWorkingDays >= 0) {
// Moving Forward
if (!blnIncSat && blnIncSun) {
intOffset = intStartDay;
} else {
intOffset = intStartDay - 1;
}
// Special start Saturday rule for 5 day week
if (intStartDay == 6 && !blnIncSat && !blnIncSun) {
intOffset -= 6;
intModifier = 1;
}
} else {
// Moving Backward
if (blnIncSat && !blnIncSun) {
intOffset = intStartDay - 6;
} else {
intOffset = intStartDay - 5;
}
// Special start Sunday rule for 5 day week
if (intStartDay === 0 && !blnIncSat && !blnIncSun) {
intOffset++;
intModifier = 1;
}
}
// ~~ is used to achieve integer division for both positive and negative numbers
newDate.setDate(datStartDate.getDate() + new Number((~~((lngNumberOfWorkingDays + intOffset) / intWorkingDays) * intNonWorkingDays) + lngNumberOfWorkingDays + intModifier));
return newDate;
}
I need to now add some dates to this function for it to take into account, these are public holiday's in Sydney Australia. What I am looking to achieve is the following.
var newDate = addWorkingDays('30/09/2015', 3, false, false);
In this example the returned date would fall on the 03/10/2015 which is a public holiday and therefore we would need to return the 04/10/2015
The dates in question are:
01/01/2015 New Year's Day
26/01/2015 Australia Day
09/03/2015 Labour Day / Eight Hours Day / Adelaide Cup / Canberra Day
03/04/2015 Good Friday
06/04/2015 Easter Monday
25/04/2015 ANZAC Day
08/06/2015 Queen's Birthday
03/08/2015 Bank Holiday / Picnic Day
05/10/2015 Labour Day
03/11/2015 Melbourne Cup
25/12/2015 Christmas Day
26/12/2015 Boxing Day
Given the function above can someone help me to amend the function to take these dates into account.
As it is your code gives me errors when I try to call it like you specify, but regardless you should simply be able to check if the date you're going to give as an answer is one of your invalid dates, and if so then return the next working day:
(pseudocode)
newDate.setDate(datStartDate.getDate() + new Number((~~((lngNumberOfWorkingDays + intOffset) / intWorkingDays) * intNonWorkingDays) + lngNumberOfWorkingDays + intModifier));
if (newDate == "01/01/2015" || newDate == "26/01/2015" || ....) {
return addWorkingDays(newDate, 1, blnIncSat, blnIncSun);
}
else {
return newDate;
}

Display Date 1 Week Ago & Yesterdays Date

I'm trying to display 2 dates (local time), the exact date a week ago from today and the exact date yesterday with as little javascript as possible
Examples:
A week ago displayed as 10/07/14
and a day ago displayed as 10/12/14
I'm trying to display it in this way
<p>The date a week ago was <span id="weekago"></span></p>
<p>The date yesterday was <span id="yesterday"></span></p>
Though it would still take some javascript, you could do it like in this jsfiddle:
this helps to retract some days of the Date
Date.prototype.subtractDays = function(nrOfDays) {
var day = 1000 * 60 * 60 * 24;
return new Date(this - (day * nrOfDays));
}
this helps for the formatting (pad left)
Object.prototype.padLeft = function(char, nr) {
var s = this.toString();
while (s.length < nr) {
s = char + s;
}
return s;
};
this formats as you want it
Date.prototype.formatStandard = function() {
return (this.getMonth() + 1).padLeft('0', 2) + '/' +
(this.getDate()).padLeft('0', 2) + '/' +
this.getFullYear();
};
and this gets the elements containing a datefield (tag name would be datefield), and i opted to rather choose data-value as an attribute to choose which date to show (as you could have more than one weekago or yesterday field)
function encodeDateFields() {
var elems = document.getElementsByName('datefield'), i, len, item, value;
if (elems === null || !elems.length) {
alert('No fields found!');
return;
}
for (i = 0, len = elems.length; i < len; i++) {
item = elems[i];
value = item.getAttribute('data-value');
switch (value) {
case 'weekago':
item.innerHTML = new Date().subtractDays(7).formatStandard();
break;
case 'yesterday':
item.innerHTML = new Date().subtractDays(1).formatStandard();
break;
default:
item.innerHTML = value + ' wasn\'t found!';
}
}
}
and the function is called onDomReady (with jsfiddle)
encodeDateFields();
I made the following changes to your html
<p>The date a week ago was <span name="datefield" data-value="weekago"></span></p>
<p>The date yesterday was <span name="datefield" data-value="yesterday"></span></p>
You would need to code in any extra data-value attributes you might have, like now or tomorrow, but it should be quite obvious where you could do it :)

Check if weekend exist in date range using javascript

Wondering if anyone has a solution for checking if a weekend exist between two dates and its range.
var date1 = 'Apr 10, 2014';
var date2 = 'Apr 14, 2014';
funck isWeekend(date1,date2){
//do function
return isWeekend;
}
Thank you in advance.
EDIT Adding what I've got so far. Check the two days.
function isWeekend(date1,date2){
//do function
if(date1.getDay() == 6 || date1.getDay() == 0){
return isWeekend;
console.log("weekend")
}
if(date2.getDay() == 6 || date2.getDay() == 0){
return isWeekend;
console.log("weekend")
}
}
Easiest would be to just iterate over the dates and return if any of the days are 6 (Saturday) or 0 (Sunday)
Demo: http://jsfiddle.net/abhitalks/xtD5V/1/
Code:
function isWeekend(date1, date2) {
var d1 = new Date(date1),
d2 = new Date(date2),
isWeekend = false;
while (d1 < d2) {
var day = d1.getDay();
isWeekend = (day === 6) || (day === 0);
if (isWeekend) { return true; } // return immediately if weekend found
d1.setDate(d1.getDate() + 1);
}
return false;
}
If you want to check if the whole weekend exists between the two dates, then change the code slightly:
Demo 2: http://jsfiddle.net/abhitalks/xtD5V/2/
Code:
function isFullWeekend(date1, date2) {
var d1 = new Date(date1),
d2 = new Date(date2);
while (d1 < d2) {
var day = d1.getDay();
if ((day === 6) || (day === 0)) {
var nextDate = d1; // if one weekend is found, check the next date
nextDate.setDate(d1.getDate() + 1); // set the next date
var nextDay = nextDate.getDay(); // get the next day
if ((nextDay === 6) || (nextDay === 0)) {
return true; // if next day is also a weekend, return true
}
}
d1.setDate(d1.getDate() + 1);
}
return false;
}
You are only checking if the first or second date is a weekend day.
Loop from the first to the second date, returning true only if one of the days in between falls on a weekend-day:
function isWeekend(date1,date2){
var date1 = new Date(date1), date2 = new Date(date2);
//Your second code snippet implies that you are passing date objects
//to the function, which differs from the first. If it's the second,
//just miss out creating new date objects.
while(date1 < date2){
var dayNo = date1.getDay();
date1.setDate(date1.getDate()+1)
if(!dayNo || dayNo == 6){
return true;
}
}
}
JSFiddle
Here's what I'd suggest to test if a weekend day falls within the range of two dates (which I think is what you were asking):
function containsWeekend(d1, d2)
{
// note: I'm assuming d2 is later than d1 and that both d1 and d2 are actually dates
// you might want to add code to check those conditions
var interval = (d2 - d1) / (1000 * 60 * 60 * 24); // convert to days
if (interval > 5) {
return true; // must contain a weekend day
}
var day1 = d1.getDay();
var day2 = d2.getDay();
return !(day1 > 0 && day2 < 6 && day2 > day1);
}
fiddle
If you need to check if a whole weekend exists within the range, then it's only slightly more complicated.
It doesn't really make sense to pass in two dates, especially when they are 4 days apart. Here is one that only uses one day which makes much more sense IMHO:
var date1 = 'Apr 10, 2014';
function isWeekend(date1){
var aDate1 = new Date(date1);
var dayOfWeek = aDate1.getDay();
return ((dayOfWeek == 0) || (dayOfWeek == 6));
}
I guess this is the one what #MattBurland sugested for doing it without a loop
function isWeekend(start,end){
start = new Date(start);
if (start.getDay() == 0 || start.getDay() == 6) return true;
end = new Date(end);
var day_diff = (end - start) / (1000 * 60 * 60 * 24);
var end_day = start.getDay() + day_diff;
if (end_day > 5) return true;
return false;
}
FIDDLE
Whithout loops, considering "sunday" first day of week (0):
Check the first date day of week, if is weekend day return true.
SUM "day of the week" of the first day of the range and the number of days in the lap.
If sum>5 return true
Use Date.getDay() to tell if it is a weekend.
if(tempDate.getDay()==6 || tempDate.getDay()==0)
Check this working sample:
http://jsfiddle.net/danyu/EKP6H/2/
This will list out all weekends in date span.
Modify it to adapt to requirements.
Good luck.

Categories

Resources