Make Calendar as 2D Array - javascript

I am trying to make a calendar as a HTML table. It should be a single 2D array with each row as a week and each column as a day. The Week start needs to be a Monday and there must be blank spaces for overlapping months.
The Issue is the Start Days are wrong for every month and differently wrong each time. January 1st 2019 was a Tuesday so i expect the Start Day to be a 2, however i get 4 (a Thursday), the same issue is for every other month.
I am using functions to get the amount of days in the month and the day the month starts on
function month_days(month, year) {return new Date(year, month, 0).getDate();}
function month_start(month, year) {return new Date(year, month, 0).getDay();}
My problem is with the month_start function.
//date is an date object generated on the fly using date.setMonth() and date.setYear();
var month_2D_arr = gen_days(date.getMonth()+1, date.getFullYear());
function gen_days(month, year){
var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var checking = new Date(year, month, 0);
console.log(monthNames[checking.getMonth()]);
console.log(checking.getFullYear());
var days = mondays(month, year);
var start = monstart(month, year);
console.log("start="+start);
}
The outputs are as follows (I induced the actual day names manually) compared to what the are suppose to be (to the right of "||").
My Results || Actual Days
January = 4 - Thursday || January = 2 - Tuesday
February = 4 - Thursday || February = 5 - Friday
March = 0 - Sunday || March = 5 - Friday
April = 2 - Tuesday || April = 1 -Monday
May = 5 - Friday || May = 3 - Wednesday
June = 0 - Sunday || June = 6 - Saturday
July = 3 - Wednesday || July = 1 - Monday
August = 6 - Saturday || August = 4 - Thursday
September = 1 - Monday || September = 0 - Sunday
October = 4 - Thursday || October = 2 - Tuesday
November = 6 - Saturday || November = 5 - Friday
December = 2 - Tuesday || December = 0 - Sunday
Example console log:
December //(month)
2019 //(year)
start=2 //(start day)
I have also switched set/getFullYear() to set/getYear() accounting for the 1900 difference and checking still. There is no difference to it.

Been playing with a calendar for giggle this week, so perhaps I can offer some help.
JS uses Sunday(0) as the first day of the week, yet you'd also like to use Monday(1)
You can create a date object that corresponds to the first day of any given month and then from that, you can deduce the day of the week of the 1st.
The approach I've employed was to create a table with 7 rows and 7 columns. The first row only contains th elements with the day names in em.
The next 42 table-cells can then be collected into an array and the correct date assigned to them. For that, I create a 42 element array using the brilliantly-named function test3.
Here's a screen:
function getFirstDayOfMonth(zeroBasedMonthNum, fullYear)
{
var monthNames = ['January','Febuary','March','April','May','June','July','August','September','October','November','December'];
var dateStr = `${monthNames[zeroBasedMonthNum]} 1, ${fullYear}, 00:00:00`;
var monthStart = new Date( dateStr );
return monthStart;
}
function daysInMonth(zeroBasedMonthNumber)
{
var days = [31,28,31,30,31,30, 31,31,30, 31,30,31 ];
return days[zeroBasedMonthNumber];
}
function MonthDay(number,isThisMonth)
{
this.day = number;
this.thisMonth = isThisMonth;
return this;
}
function test3(monthIndex, year)
{
var firstDay = getFirstDayOfMonth(monthIndex, year).getDay();
if (firstDay == 0)
firstDay = 6;
else
firstDay--;
var daysFromLastMonth = firstDay;
var result = [];
var daysInLastMonth = daysInMonth(monthIndex-1);
var first = daysInLastMonth - daysFromLastMonth + 1;
console.log(first);
for (var i=0; i<daysFromLastMonth; i++)
{
//result.push(first+i);
result.push( new MonthDay(first+i, false) );
}
for (var i=1; i<= daysInMonth(monthIndex); i++)
//result.push( i );
result.push( new MonthDay(i,true) );
var daysDone = result.length;
var daysToGo = (6*7) - daysDone;
for (var i=1; i<=daysToGo; i++)
//result.push( i );
result.push( new MonthDay(i,false) );
return result;
}

Related

How to set date back by n months in Javascript

For example the month is June 2020. I want to be able to go back by 12 months, and retrieve the date as June/July 2019.
let month_val = 6;
let year_val = 2020;
let n_val = 12;
let month_names = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
let date = new Date();
let end_month_text = month_names[month_val - 1];
end_month_text += " " + year_val;
date.setMonth(month_val); //set to month in URL
date.setMonth(date.getMonth() - n_val); //setting back by n_val months
let start_month_text = month_names[date.getMonth()];
start_month_text += " " + date.getFullYear();
console.log(start_month_text + " - " + end_month_text);
The problem lies with the second to last line, date.getFullYear() returns the current real year (-12) not last year set back 12 months ago. How can I set the date back 12 months so when I attempt to date.getFullYear() I get one year ago?
The problem with using a Date as in the OP is that in setting the month, you may set it to a date that doesn't exist, e.g. on 31 July setting the date to June gives 31 June, which rolls over to 1 July. You can check and correct for those types of errors, but it's better to just avoid them.
If you just want to generate a 12 month date range based on whole months, you don't need to get that fancy. Given an end month and year, the start will be the month + 1 and year - 1, unless the start month is December in which case the end must be January of the same year, e.g.
// month is calendar month number, 1 == Jan
function getMonthName(month = new Date().getMonth() + 1) {
// Use a Date to get the month name
return new Date(2000, month - 1).toLocaleString('en',{month:'long'});
}
// month is end calendar month number
// year is end year
function getDateRange(month, year) {
// If month is 12, don't subtract 1 from year
return `${getMonthName(month+1)} ${year - (month == 12? 0 : 1)} - ` +
`${getMonthName(month)} ${year}`;
}
// Range ending June 2021
console.log(getDateRange(6, 2021)); // July 2020 - June 2021
// Range ending December 2021
console.log(getDateRange(12, 2021)); // January 2021 - December 2021
// Range ending January 2021
console.log(getDateRange(1, 2021)); // February 2020 - January 2021
// Range ending in current month and year
let d = new Date();
console.log(getDateRange(d.getMonth() + 1, d.getFullYear()));
The getMonth function could use any language, or for just one language could be replaced with an array of month names.

How to calculate last date of last 5 financial years. if current date is greater or lesser than 31st march

if current date is greater than 31st march then the output should be (31st march 2021,31st march 2020,31st march 2019,31st march 2018,31st march 2017).if current date is lesser than 31st march then the output should be (31st march 2020,31st march 2019,31st march 2018,31st march 2017,31st march 2016)
You can get the start year based on whether the date is before or after 31 March, then get the 5 prior instances of that date.
The function can be made more general by allowing the user to specify the number of dates to get while defaulting to 5. E.g.
// Get previous n dates for 31 March from date
function getYears(date = new Date(), n = 5) {
let year = date.getFullYear();
year -= date < new Date(year, 3, 1)? 1 : 0;
return new Array(n).fill().map(() => new Date(year--, 2, 31));
}
// Examples
console.log('Start today');
getYears().forEach(d=>console.log(d.toDateString()));
console.log('\nStart 1 Jan 2020');
getYears(new Date(2020,0)).forEach(d=>console.log(d.toDateString()));
console.log('\nGet 10 years, start today');
getYears(new Date(), 10).forEach(d=>console.log(d.toDateString()));
The method will get the current date & will compare with the current year march,31 dates. If the current date is greater than Mar,31 then it will add the next 5-year date of 31-March. If the current date is less than Mar,31 then it will add the previous 5-year date of 31-March.
function getYearList(){
var yearList = [];
var currentDate=new Date();
//new Date(year, month, day, hours, minutes, seconds, milliseconds)
// Here 00=Jan,01=Feb,02=Mar etc.
var comparingDate=new Date(currentDate.getFullYear(),02,31);
var yearCount=currentDate.getFullYear();
if(currentDate>=comparingDate){
for (let i = 0; i <= 4; i++) {
var newDate=new Date((yearCount+i),02,31);
yearList.push(newDate);
}
}else{
for (let i = 4; i >= 0; i--) {
var newDate=new Date((yearCount-i),02,31);
yearList.push(newDate);
}
}
console.log(yearList);
}
PeriodChange(event: any) {
this.YearMap=[];
this.currentYear = (new Date()).getFullYear();
this.selectedYears = 5;
this.SelectedCertificate = Number(this.selectedYears);
const comparisondate = "March 31 " + this.currentYear;
const requiredDate = new Date(comparisondate);
requiredDate < new Date() ? this.increment=0 : this.increment=1;
for (let i = 0; i < Number(this.CACertificateselectedYears); i++) {
this.YearMap.push("31 March "+(this.currentYear-this.increment));
this.currentYear-=this.increment;
console.log(this.YearMap);
this.increment === 1 ?this.increment :this.increment++;
}
}

How to get Monday of a week as a number

I would like to get the first day of a week in a given year (assuming the week starts on a Monday).
Scenario: The year is 2016. It should return 4, because Monday the 4th of January 2016 is the first day of week 1 in 2016.
How would I do that? I want something like this:
var date = new Date();
var week = 1;
var year = 2016;
date.getMonday(week, year); // 4 (because 04/01/2016 is a Monday and is week number 1)
week = 5;
date.getMonday(week, year); // 30 (because 30/01/2016 is a Monday and is week number 5)
Thanks
You can use JavaScript's getDay() method to figure out which day of the week a date object refers to.
var output = document.getElementById('output');
var year = 2016;
var firstMonday = new Date(year, 0, 1); // year, month (zero-index), date
// starting at January 1st, increment the date until a Monday (`getDay() = 1`)
while(firstMonday.getDay() !== 1) {
firstMonday.setDate(firstMonday.getDate() + 1);
}
// output the date of the first Monday in January
output.value = firstMonday.getDate();
<textarea id="output"></textarea>
I've made a function to solve this... see bellow
function getDayInWeek(dayOfWeek, week, year){
dayOfWeek = dayOfWeek % 7; //ensure day of week
var baseDate = new Date(year, 0, 1); //get the first day
var firstDayOfWeek = baseDate.getDay(); //get the first week day
var inWeek = (week - 1) * 7; //get the days to start of week
var diff = firstDayOfWeek - dayOfWeek; //get the diff for day in that week
if(diff < 0) diff += 7;
baseDate.setDate(inWeek + diff);
return baseDate.getDate(); //get the month day
}
to use specify the week day
// 0 = sunday
// 1 = monday
// 2 = tuesday
// 3 = wednesday
// 4 = thursday
// 5 = friday
// 6 = saturday
var firstMonday = getDayInWeek(1, 1, 2016); // the monday in first week of 2016
var mondayOf5 = getDayInWeek(1, 5, 2016); // the monday in 5th week of 2016
To get ISO-8601 week, which will always be a Monday, see link:
Wikipedia
Calculate ISO 8601
function getISOWeek(week, year) {
var _date = new Date(year, 0, 1 + (week - 1) * 7);
var date_of_week = _date.getDay();
var ISOweekStart = _date;
(date_of_week <= 4) ? ISOweekStart.setDate(_date.getDate() - _date.getDay() + 1): ISOweekStart.setDate(_date.getDate() + 8 - _date.getDay());
return ISOweekStart;
}
console.log(getISOWeek(10, 2016));

Getting values from a textarea and storing them correctly

I am writing a JavaScript program to determine what day of the week a given date can fall on. The user types the date in a textbox and then presses submit.
The ways a date can be entered is:
Day/Month/Year --> 6/15/95 for June 6th, 1995
6/15/1995 for the same date
Day Month Year --> 15 September 2006
Month Day Year --> February 19, 1994
I got it to accept the Day/Month/Year and Month Day, Year, but for some reason I cannot get it to accept it with the day followed by the month. Here is my code so far.
var monthArray = ["January", "February", "March",
"April", "May", "June", "July",
"August", "September", "October",
"November", "December"];
var month;
var day;
var year;
var text1 = getElementById("myTextArea").value;
var text2 = text1.split(/[\s\/,]+/); //15 Sep 2001 will be ["15", "Sep", "2001"]
//6/13/95 will be ["6", "13", "95"]
//Sep 15, 2001 will be ["Sep", "15", "2001"]
for(var i = 0; i < text2.length; i++) //Iterate through all elements in text2
{
for(var j = 0; j < monthArray.length; j++) //Iterate through all elements in monthArray
{
if(text2[i].substring(0, 3) == monthArray[j].substring(0, 3)) //See if one of the elements matches a month string.
{
month = j + 1; //Set month equal to the number. For instance, if Sep month = 9
text2.splice(i, i + 1); //Remove the month element. Array should contain ["date", "year"] in that order
day = text2[0]; //Set day equal to the "date" element.
year = text2[1]; //Set year equal to the "year" element.
}
}
}
if(typeof month == "undefined") //This will happen if month isn't a string. I.e. it is a number like 5/16/54.
{
month = text2[0];
day = text2[1];
year = text2[2];
}
//This is for a specified year range.
if(year >= 50 && year < 100)
{
year = 1900 + parseInt(year);
}
else if(year <= 49 && year >= 0)
{
year = 2000 + parseInt(year);
}
When I enter something like 6/15/95 or June 15, 1995 it works fine. But for some reason if I try to enter 15 June 1995, it won't work and I have no idea why. Can anyone spot my mistake? I've been messing with this for hours with no avail. Is there an easier way to do this? Any way I can do this with just some regular expressions? I feel like I am making this way harder than I need to. Thanks.
text2.splice(i, i + 1); is causing text2[i] to become undefined on the next loop iteration if there is a month match. You are then trying to call substring on undefined which is throwing an error.
I'm guessing if there is a month match you will want to break out of the for loop.
Your code is unclear.
Readable is more important.
Split your code into several functions first. Then union them to erase duplicated code.
function detectFormat
function transferSlashFormat
function transferSpaceFormat
function transferCommaFormat
Make every function works.
Then union 2-4 function, erase duplicated code.
You can get a Date out of a string like this:
var string = "Sep 15, 2001";
var d = new Date(string)
it will return a Date Object, which you can then manipulate however you want,
and it works with all your given examples.

Is there an easy way to find the last date a day of week occurs in the current month

I am trying to display the date of the last Wednesday in the current month... so that it will automatically change to the correct date when the next month occurs. (So instead of having to say: "Performing the last wednesday of every month", I can dymanmically give the actual date.)
For example, I would want the date to show on the webpage as Wednesday, Sept 25th for this month, and then appear as Wednesday, Oct 30th next month.
A bonus additional solution would be if I could get the next month's date to display after the previous date has past. In my above example, when the current date is Sept 26-30 (any date after that last wednesday, but still in the same month).. the date would show the next performance date of Oct 30th.
It would be great if the solution was through html, javascript/jquery or asp.
Thanks,
SunnyOz
It depends on your criteria for "easy". Here's a simple function to do as required, it's 5 lines of working code that can be reduced to 4, but will lose a bit of clarity if that's done:
function lastDayInMonth(dayName, month, year) {
// Day index map - modify to suit whatever you want to pass to the function
var dayNums = {Sunday: 0, Monday:1, Tuesday:2, Wednesday:3,
Thursday:4, Friday:5, Saturday:6};
// Create a date object for last day of month
var d = new Date(year, month, 0);
// Get day index, make Sunday 7 (could be combined with following line)
var day = d.getDay() || 7;
// Adjust to required day
d.setDate(d.getDate() - (7 - dayNums[dayName] + day) % 7);
return d;
}
You can change the map to whatever, just determine what you want to pass to the function (day name, abbreviation, index, whatever) that can be mapped to an ECMAScript day number.
Edit
So in the case of always wanting to show the last Wednesday of the month or next month if it's passed:
function showLastWed() {
var now = new Date();
var lastWedOfThisMonth = lastDayInMonth('Wednesday', now.getMonth()+1, now.getFullYear());
if (now.getDate() > lastWedOfThisMonth().getDate()) {
return lastDayInMonth('Wednesday', now.getMonth()+2, now.getFullYear());
} else {
return lastWedOfThisMonth;
}
}
Note that the function expects the calendar month number (Jan = 1, Feb = 2, etc.) whereas the getMonth method returns the ECMAScript month index (Jan = 0, Feb = 1, etc.) hence the +1 and +2 to get the calendar month number.
You could use a javascript library such as moment.js:
http://momentjs.com/
and then get it with this:
moment().add('months', 1).date(1).subtract('days', 1).day(-4)
Here is an approach in JS:
var monthLengths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
function getLastWednesday() {
var d = new Date();
var month = d.getMonth();
var lastDay = monthLengths[month];
// mind leap years
if (month == 1) {
var year = d.getFullYear();
var isLeapYear = ((year % 4 == 0 && year % 100 > 0) || year % 400 == 0);
if (isLeapYear) lastDay++;
}
// get the weekday of last day in the curent mont
d.setDate(lastDay);
var weekday = d.getDay();
// calculate return value (wednesday is day 3)
if (weekday == 3) {
return lastDay;
}
else {
var offset = weekday - 3;
if (offset < 0) offset += 7;
return lastDay - offset;
}
}
I prefer to use an abstraction like moment.js as #Aralo suggested. To do it in raw JavaScript, however, you can use some code like this... create a function that gets all the days in a month. Then reverse-traverse the list to find the last day number. Wednesday is 3.
function getDaysInMonth(date) {
var dayCursor = new Date(today.getFullYear(), today.getMonth()); // first day of month
var daysInMonth = [];
while(dayCursor.getMonth() == date.getMonth()) {
daysInMonth.push(new Date(dayCursor));
dayCursor.setDate(dayCursor.getDate() + 1);
}
return daysInMonth;
}
function findLastDay(date, dayNumber) {
var daysInMonth = getDaysInMonth(date);
for(var i = daysInMonth.length - 1; i >= 0; i--) {
var day = daysInMonth[i];
if(day.getDay() === dayNumber) return day;
}
}
Then, to get the last Wednesday in the current month:
var today = new Date();
var lastWednesday = findLastDay(today, 3);

Categories

Resources