Sorting based on upcoming birthday - javascript

I'm building a simple birthday reminder app where I get the names and birthdays in JSON and I need to display the names sorted based on whose birthday is coming next.
My logical thought would be to get the current day and month subtract that from the birthday and then do some kind of sort. But then how would do I handle -ve results or situations like when we are in Dec etc. I was guessing there might have been an simpler solution, but I'm quite clueless.
Here is a plunkr with the base working code: http://plnkr.co/edit/AkP6FRRG917TDdTtfWM7?p=preview

As others suggested, convert the string to a unix timestamp or date.
Here's an updated Plunker.
The controller adds a fromNow variable to the data:
$scope.friends.forEach(function(data){
var day = data.birthday.split("/")
var currentYear = new Date().getFullYear();
var birthdayDate = new Date(currentYear, day[0] - 1, day[1])
var now = new Date().valueOf();
if (birthdayDate.valueOf() < now){
birthdayDate.setFullYear(currentYear+1)
}
data.fromNow = birthdayDate.valueOf() - now;
})
Get the individual date/month parts (so we get a list like ["02","14","1985"])
Create a date object based on the current year, the month day[0] and the day day[1]. (Note we subtract 1 from the months because months are 0-based in in Javascript).
Get a numeric value for the current date/time
If the birthday is in the past add one year
Assign the number of milliseconds between now and the birthday to fromNow
You'd need to modify it so that if someone's birthday is today it doesn't add a year, thus placing it last in the list.
Also note I've added quotes to the orderBy parameter:
<tr ng-repeat="friend in friends| orderBy:'fromNow' ">

I would go about this by converting the dates to unix timestamps (int values) and doing a simple sort on them.
Convert date to timestamp using javascript Date.parse()

Convert the current date and birthdate to UNIX time and compare them based on the differences between these two values
birthdates = [new Date(1988,01,27), new Date(2013,01,01)];
birthdates.sort(function(firstDate,secondDate){
//calculate the difference between first date and current date
firstDifference = new Date() - firstDate;
//calculate difference between second date and current date.
secondDifference = new Date() - secondDate;
//return the smallest value.
return firstDifference - secondDifference;
});
//display the sorted array.
alert(birthdates);

Related

Compute an age with d3-time

I'm trying to compute the age of an individual using D3.js.
I have the following code :
d3.timeYear.count(Birth_date, Current_date);
Birth_date being an individual's birth date (a Date object), and Current_date being, well, the date at which I'd like to compute the individual's age. To be able to answer "if you were born on May 5th, 1975, how old were you on May 3rd, 1976".
d3.timeYear.count() seems to floor the dates to the beginning of the year, so that in my example my code will return 1 on January 1st, 1976, even though the guy was 5 months away from his first birthday.
I could count the number of days instead of years, but I might get wrong results locally depending on the number of days in the year.
The following is based on the JavaScript Date object and should do the job:
function age(by,bm,bd){
const D=new Date(), y=D.getFullYear(),
md=D.getMonth()-bm, dd=D.getDate()-bd;
return y-by-(md>0||!md&&dd>=0?0:1);
}
console.log(age(1992,8,26))
Basically I return the difference between the full year of today and the birthday. But I also check, whether the current month is either greater than the birthday-month or (||) if the month-difference is zero (!md is true) and (&&) the day-difference dd is greater than zero. If that is the case I subtract 0 otherwise 1 from the year-difference.
And please be aware that my age() function expects the month to be entered in JavaScript notation. This means that 8 in the above example refers to the month of September.
The answer by Carsten Massman has inspired me to make this function, which solves my problem :
function age(birthdate, currentdate){
const bDay = birthdate.getDate(); // Get the birthdate's day.
const bMonth = birthdate.getMonth(); // Get the birthdate's month.
const currYear = currentdate.getFullYear(); // Get the current date's year.
const currBirthday = new Date(currYear + "/" + (bMonth + 1) + "/" + bDay); // Contruct the date of the birthday in the current year
const daysToBirthday = d3.timeDay.count( d3.timeYear.floor(currBirthday), currBirthday); // Count the # of days since Jan. 1st this year
// Offset the current date in the past by the number of days computed above.
const offsetCurrent = d3.timeDay.offset(currentdate, -daysToBirthday);
// Compute the number of years between the two dates (floored to the beginning of their respective year).
return d3.timeYear.count(birthdate, offsetCurrent);
}
This computes the age for any birth date, and at any point in time afterwards, using mostly d3-time and a little bit of vanilla javascript's Date methods.

Get all the months and year from provided ISO Date to current month and year

Suppose I have ISO Date inside an object as:
const dataCreated = {"readDetail":'2020-09-17 14:23:26.978Z'}
Is it possible to I get all date from created date till todays date.
Expected O/P ->assunming current date is jan 2021 :
['2020-09-17','2020-10-17','2020-11-17','2020-12-17','2021-01-17']
I tried different searches but was unable to get find anything related to it. If anyone has any solution or in someway can guide me that would be really helpful. If any further information needed please let me know.
What you want to do is just fill your array while looping over the dates. And with each loop add one month to your original date.
Note that you have to to create a new Instance of Date before saving it in your array since JavaScript saves references.
function getDates() {
var date = new Date("2020-09-17 14:23:26.978Z");
var now = new Date();
var datearray = [new Date(date)];
while(date.setMonth(date.getMonth() + 1) < now) {
datearray.push(new Date(date));
}
console.log(datearray);
}
Contrary to your expected output I'm saving Date Objects in the array. This has the advantage of giving you more opportunities when working with the Array elements afterwards. This could easily be changed though by changing the line where the Date object is pushed to the array.

Merging two Timezone aware date objects in javascript- one for date, the other for time

Lets say I have the following timezone aware Date objects in Javascript:
var date1 = new Date("2019-07-02T07:30:00-05:00");
var date2 = new Date("2020-08-05T00:00:00-05:00");
What is the best way to merge these two, such that I keep the time from date1 and the date from date2, yielding:
new Date("2020-08-05T07:30:00-05:00");
I've tried:
date1.setDate(date2.getDate());
date1.setMonth(date2.getMonth());
date1.setYear(date2.getYear());
which set the day and month correctly for date1, but the year is incorrectly set to "120" with the example inputs above.
A few things:
Date objects cannot be time zone aware. When passed a string with a time zone offset like the ones you showed here, they use that offset to determine the equivalent UTC time. Ultimately the only thing stored within the Date object is the numeric Unix timestamp that corresponds to that UTC time. You can see this with .getTime() or .valueOf().
getDay/setDay are for the day of the week, Saturday (0) through Sunday (6). Use getDate/setDate for the day of the month.
getYear/setYear are for two-digit years (or rather the current year minus 1900), and should not be used ever. Use getFullYear/SetFullYear instead.
Because of the first point, what you ask is not possible. Or at least, not possible with the full range of values that might be encountered in such strings. Instead, you can manipulate the strings directly, or you can use a library such as Luxon or Moment.
I'd also think a bit harder about what you're actually trying to accomplish. Where do these two values come from? Why are portions of the data important and others to be discarded? What will you do if the offsets are different between the two values? Only you can answer these points.
Manipulate the ISO strings directly:
const date1 = new Date("2019-07-02T07:30:00-05:00");
const date2 = new Date("2020-08-05T00:00:00-05:00");
const date3 = new Date([
date2.toISOString().split('T')[0],
'T',
date1.toISOString().split('T')[1],
].join(''));
console.log({date1, date2, date3});
By the way, there is no "timezone-aware" date objects. Once Date(...) is fired, time is UTC. getTimezoneOffset gets the difference from the local timezone to UTC.

Date restrictions on user input in JavaScript

I am trying to have a date entry box which has the following restrictions. Date must be today's date or earlier, but not more than 1 year previous. I have the following line:
if (myFDGDT - todayDate > 0 || (myFDGDT - todayDate)/86400000 < -365)
The first portion of that creates the appropriate alert when some enters a date after today's date. Not sure about the best way to cap the entry to a year previous. Attempted a few items, but the above was just an example of my last attempt. This is also written in a dependency and not in the Global JavaScript of our entry client.
Here is a snippet that will generate a Date object that is one year ago. You can compare against it as needed using greater than/less than operators.
var oneyear = new Date('01/01/1971'); // from unix epoch
var now = new Date();
var oneyearago = new Date(now - oneyear);
alert(oneyearago);
If you are manipulating dates a lot in your app you should consider using the momentjs library. For your problem the solution would be something like:
var momentdate = moment(date);
if (momentdate.isAfter(momentdate.add(1, 'year') ||
momentdate.isBefore(momentdate.startOf('day')) {
// Invalid date?
}
Hope this helps.

Date to epoch and vice versa - JavaScript

I need to convert date to Java epoch and then read it and convert back. Not sure what I'm doing wrong here?
var date = new Date('1/3/2013');
var timeStamp = date.getTime();
console.log(timeStamp);
var revertDate = new Date(timeStamp);
console.log(revertDate.getDate()+'/'+revertDate.getMonth()+'/'+revertDate.getFullYear());
The output is 3/0/2013 instad 1/3/2013?
fiddle link
You've got two problems here:
The Date constructor is assuming M/d/yyyy format - whereas you're logging d/M/yyyy format. Personally I'd suggest using an ISO-8601 format if at all possible: yyyy-MM-dd
You're not taking into account the fact that getMonth() returns a 0-based value
For the formatting side, you'd be better off using toISOString or something similar, rather than doing the formatting yourself.
(Note that looking at the documentation for the Date constructor it's not clear that the code you've got should work at all, as it's neither an RFC822 nor ISO-8601 format.)
Neither of the problems are to do with converting between Date and a numeric value. If you change your logging, you'll see that clearly:
var date = new Date('1/3/2013');
var timeStamp = date.getTime();
console.log(date);
var revertDate = new Date(timeStamp);
console.log(revertDate);
var date = new Date('1/3/2013');
The Date constructor is parsing this given string this way:
Month / Day / Year
So, in this case, Month is 1, Day is 3 and Year is 2013. What's going on there? Well that's quite simple. This Gregorian representation of a date(which is specifically Day / Month / Year ) isn't the one used by the Date constructor, so it will parse the 1(the month) as January, the 3 as the third day of the month(the third of Jan) and the year correctly, the 2013. Now, due to its 0-based indexing, the constructed Date object will return a month which is n-1 among the one provided. That's why you're getting 3/0/2013. It is the third day(3) of the month 0(which is January) of 2013. If you want to get your real date you have to do this:
var date = new Date('3/1/2013');
console.log(date.getDate()+'/'+(date.getMonth()+1)+'/'+date.getFullYear());

Categories

Resources