display a calendar year with custom hyperlinks in asp.net mvc - asp.net-mvc

I'm looking to create an MVC web page that displays the 12 months of the year in a calendar format. Inside each day in the month I will bold only the dates that have any activity (data from database). The dates with activity would also be hyperlinked to a route like /Activity/2008/12/25
i'm about to attempt to try the asp.net ajax control toolkit calendar control but was wondering if anyone else had any advice.

Rendering a calendar is not extremely complicated. By using DateTimeFormatInfo in System.Globalization and the DateTime all the necessary information can be retrieved:
DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek
DateTimeFormatInfo.CurrentInfo.GetMonthName(month)
DateTimeFormatInfo.CurrentInfo.GetAbbreviatedDayName((DayOfWeek)dayNumber)
A month in the calendar can be rendered in a table:
_ _ _ 1 2 3 4
5 6 7 8 9 ...
To dermine the number of empty cells at the begining something like this can be used:
DateTime date = new DateTime(year, month, 1);
int emptyCells = ((int)date.DayOfWeek + 7
- (int)DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek) % 7;
As there are maximum 31 days in a month and maximum 6 empty cells at begining, a month can be rendered on maximum Ceil(37 / 7) = 6 rows. So there are maximum 42 cells to render in a month, some of them will be empty.
A new row is inserted in the table each 7 (number of days in a week) cells.
int days = DateTime.DaysInMonth(year, month);
for (int i = 0; i != 42; i++)
{
if (i % 7 == 0) {
writer.WriteLine("<tr>");
if( i > 0 ) writer.WriteLine("</tr>");
}
if (i < emptyCells || i >= emptyCells + days) {
writer.WriteLine("<td class=\"cal-empty\"> </td>");
} else {
writer.WriteLine("<td class=\"cal-day\"\">" + date.Day + "</td>");
date = date.AddDays(1);
}
}
Also, simply add an additional link in the non-empty cells to the desired route when the dates are with activity.

Related

Calculating Age in X++

I am trying to calculate an age in x++ where the customer is born on 1/6/2010 to the selected day of his visit - 1/6/2023 today but the result doesn't give me 13 years old but gives me 12.
real ageDiffReal;
int ageDiffInt;
date datetoday = DateTimeUtil::date(Visitas.RFC_DataVisita);
ageDiffReal = (datetoday - mkDate(dir.BirthDay,dir.BirthMonth,dir.BirthYear)) / 365.242199;
ageDiffInt = Round(ageDiffReal,0);
info(strFmt('%1,%2',ageDiffReal, ageDiffInt));
I tried with / 365 and with 365.25 because of leap years but still didn't work well
You're using round(...) incorrectly.
ageDiffInt = decRound(ageDiffReal, 0); // Better
ageDiffInt = round(ageDiffReal, 1); // Works too
round(...) - The number that is a multiple of the value specified by the _decimals parameter and is closest to the value specified by the _arg parameter.
See https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-ref/xpp-math-run-time-functions

Is my Twilio function correct for routing a call based on day of week and time of day?

I'm trying to route calls to different agents based on time of day using Twilio Studio referencing the following function and wondering if it's correct? I'm not a programmer, so this is adapted from Need help creating a Time Gate in Twilio Function
// Time of Day Routing
// Useful for IVR logic, for Example in Studio, to determine which path to route to
// Add moment-timezone 0.5.31 as a dependency under Functions Global Config, Dependencies
const moment = require('moment-timezone');
exports.handler = function(context, event, callback) {
let twiml = new Twilio.twiml.VoiceResponse();
function businessHours() {
// My timezone East Coast (other choices: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
const now = moment().tz('America/Denver');
// Weekday Check using moment().isoWeekday()
// Monday = 1, Tuesday = 2 ... Sunday = 7
if(now.isoWeekday() == 1 || 3 || 5 /* Check for Normal Work Week Monday - Friday */) {
//Work Hours Check, 9 am to 5pm (17:00 24 hour Time)
if((now.hour() >= 8 && now.hour() < 9:30) || (now.hour() >= 12 && now.hour() < 17) /* 24h basis */) {
return true
}
}
if(now.isoWeekday() == 2 /* Check for Normal Work Week Monday - Friday */) {
//Work Hours Check, 9 am to 5pm (17:00 24 hour Time)
if((now.hour() >= 8:30 && now.hour() < 11) /* 24h basis */) {
return true
}
}
if(now.isoWeekday() == 4 /* Check for Normal Work Week Monday - Friday */) {
//Work Hours Check, 9 am to 5pm (17:00 24 hour Time)
if((now.hour() >= 8 && now.hour() < 10:30) || (now.hour() >= 15 && now.hour() < 17) /* 24h basis */) {
return true
}
}
// Outside of business hours, return false
return false
};
const isOpen = businessHours();
if (isOpen) {
twiml.say("Business is Open");
} else {
twiml.say("Business is Closed");
}
callback(null, twiml);
};
Twilio developer evangelist here.
Stack Overflow is not the best place to ask "is this correct?". It's much better to come with an actual problem that you have and a description of the things you have tried to fix that problem. It's also hard to answer "is this correct?" if we don't know the outcome you actually want.
However, I can see one issue with the code above and that is dealing with working hours that fall outside of just on the hour tests.
now.hour() will return a whole number that is the current hour. You cannot compare this to 9:30 for example. Instead, we have to look at both the hours and the minutes,
In your first conditional hour check you have:
if((now.hour() >= 8 && now.hour() < 9:30) || (now.hour() >= 12 && now.hour() < 17) /* 24h basis */) {
return true
}
In words, you seem to be going for: If the time is between 8am and 9:30am or the time is between 12pm and 5pm then return true.
To cope with the time 9:30 we have to check that the time is between 8am and 10am and if it is some number of minutes past 9, that number of minutes is not more than 30. Just to cut down the code we are looking at, the issues is this predicate:
(now.hour() >= 8 && now.hour() < 9:30)
We could replace this with:
((now.hour() >= 8 && now.hour() < 9) || (now.hour() == 9 && now.minute() < 30))
This now tests that the hour is more than or equal to 8 and less than 9 OR that the hour is equal to 9 and the minutes are less than 30.
Since "greater than or equal to 8 and less than 9" is effectively the same as "equal to 8" we could shorten this to:
(now.hour() === 8 || (now.hour() == 9 && now.minute() < 30))
But you will want to use the full version when you want to fix further comparisons, like between 8:30 and 11 or between 8 and 10:30.
Hopefully this gives you a good idea of how to approach all your time comparisons.

Input Date to Written form

I'm trying to write an inputted date from the adjacent cell.
i.e. date entered in A1, B1 = A1 but in word form (in Spanish).
I'm close to a solution but I'm sure making things more complicated than they need to be.
The date column(A) is currently being separated into 3;
day(B), month(D), year(F), using; =LEFT($A1;2), =MID($A1;4;2), =RIGHT($A1;4) accordingly.
In Columns C,E,G I'm using
=INDEX(IMPORTXML("https://www.buscapalabra.com/numeros-a-letras.html?cifra="&B1;"//li[1]//strong");1)
where B1 changes to E1, F1 depending on the column
finally in column H where the date will be written I use:
=trim(LOwer($C2&"de "&TEXT($D2;"mmmm")&" de "&$F2))&If(Value(Right($E2;1))=1;If(Value(MID($E2;4;1))<>1;"o";"");"")
For some reason the text value returned from the site has a space on the end and also does not properly word numbers ending in 1. Hence the use of TRIM() & the nested IF()
It works for now, I haven't tested it exhaustedly but I'd love to hear what people think, I'm new to Sheets but there has to be a cleaner way to do this.
Use custom functions:
You could do this with an Apps Script Custom Function.
First, open a bound script by selecting Tools > Script editor, and copy the following functions to the script (check inline comments for more information):
function DATE_IN_WORDS(date) {
const day = date.getDate(); // Day of the month in numbers
const year = date.getFullYear(); // Year in numbers
const options = { month: 'long'};
const month = new Intl.DateTimeFormat('es-ES', options).format(date); // Month in words
const dayAndYear = [day, year].map(number => { // Retrieve word for day and year
const url = "https://www.buscapalabra.com/numeros-a-letras.html?cifra=" + number
const resp = UrlFetchApp.fetch(url).getContentText();
const first = "<em>Como sustantivo:</em> El <strong>";
const cut = resp.substring(resp.indexOf(first), resp.length);
let word = cut.substring(first.length, cut.indexOf("</strong>")); // Get desired section of HTML
if (number.toString().slice(-1) == "1" && number.toString().slice(-2) != "11") {
word = word.trim() + "o"; // Replace "un" with "uno"
let arrayWord = word.split(" ");
let lastWord = arrayWord.pop();
if (lastWord === "veintiúno") { // If 21, replace "ú" with "u"
lastWord = lastWord.replace("ú", "u");
arrayWord.push(lastWord);
word = arrayWord.join(" ");
}
return word;
} else return word;
});
return dayAndYear.join("de " + month + " de "); // Join day, month and year
}
This function uses:
Intl.DateTimeFormat to retrieve the month in Spanish.
UrlFetchApp to fetch information from https://www.buscapalabra.com/numeros-a-letras.html.
Once it is defined, you can use the function DATE_IN_WORDS the same you would any sheets built-in function. This function would accept the cell with the Date as a parameter.
Example:
Reference:
Custom Functions in Google Sheets

Iterate through range and match values

I have a spreadsheet with two sheets: Week#, Events.
Sheet "Week#" (calendar week # in Column A and the start day of this week in Column B):
01 January 4, 2016
02 January 11, 2016
03 January 18, 2016
04 January 25, 2016
05 February 1, 2016
and so on till week 52
Sheet "Events" has next columns:
Facility, Repeats, Belongs to week #, Week # starts on, Item, Action, Status.
It's filled with something like this (number of rows varies):
SalonA, monthly, 4, January 25,2016, Floor, to mop the floor, Created
The script is like this:
function createEventmanually (title, date)
{
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveRange().getRowIndex();
var EventStatus = sheet.getRange(row, 7).setValue("Created");
var title = sheet.getRange(row,1).getValue()+" "+"Week "+sheet.getRange(row,3).getValue()+" "+sheet.getRange(row,5).getValue()+":"+" "+sheet.getRange(row,6).getValue();
var cal = CalendarApp.getCalendarsByName('RM') [0];
var date = sheet.getRange(row,4).getValue();
var event = cal.createAllDayEvent(title, date);
}
I manually copy and paste calendar dates from sheet Week# to column "Week # starts on" in sheet Events. And then run the script every time to create event.
How to automatize this process? I understand that it could be done through iteration but I cannot figure it out.
Thank you in advance.
If what you want is 52 calendar events (One every week) for every different
task in the Events sheet, this code is how you would need to do it.
function createAllEventsForTheYear() {
var allRowsOfDataInEventSheet,allDataInWeekSheet,cal,eventSh,i,j,L,Lj,lastRowInEventSheet,lastRowInWeekSheet,
lastColumnInEventSheet,lastColInWeekSh,ss,row,
weekNumberSheet,rowDataBeingProcessedFromEventsSheet,thisEventTitle,thisWeeksDate;
cal = CalendarApp.getCalendarsByName('RM')[0];
ss = SpreadsheetApp.getActiveSpreadsheet();
eventSh = ss.getSheetByName('Events');
weekNumberSheet = ss.getSheetByName('Week#');
lastRowInEventSheet = eventSh.getLastRow();
lastRowInWeekSheet = weekNumberSheet.getLastRow();
lastColumnInEventSheet = eventSh.getLastColumn();
lastColInWeekSh = weekNumberSheet.getLastColumn();
allRowsOfDataInEventSheet = eventSh.getRange(2, 1, lastRowInEventSheet-1, lastColumnInEventSheet).getValues();
allDataInWeekSheet = weekNumberSheet.getRange(2, 1, lastColInWeekSh-1, lastColInWeekSh).getValues();
L = allRowsOfDataInEventSheet.length;
Lj = allDataInWeekSheet.length;
for (i=0;i<L;i+=1) { //Loop through every row of data in the Events sheet
rowDataBeingProcessedFromEventsSheet = allRowsOfDataInEventSheet[i];//Get one row of data
thisEventTitle = rowDataBeingProcessedFromEventsSheet[0] + "Week" + rowDataBeingProcessedFromEventsSheet[2] + " " + rowDataBeingProcessedFromEventsSheet[4] + ": " + rowDataBeingProcessedFromEventsSheet[5];
for (j=0;j<Lj;j+=1) {//For every row in the Events sheet, create an event for every week of the year. 52 events for this event type
thisWeeksDate = allDataInWeekSheet[j][1];//Get the date from the second column of the data in the Weeks# sheet
cal.createAllDayEvent(thisEventTitle, thisWeeksDate);
};
eventSh.getRange(i+2, 7).setValue("Created");//I starts at 0, data starts on row 2
};
};
I have not tested this, or even debugged it, so it may not run perfectly.

Formatting time for user input in ASP.Net MVC

I have a form that users are allowed to enter time values in (say, hours spent performing some task). A business requirement is that the time be entered in either hh:mm format, or decimal format. In either case, there could potentially be quite a bit of client side javascript for display "helping"--showing totals, validating against other input, etc.
So, for instance, one user might enter "8:30" for Eight Hours Thirty Minutes, while another might enter "8.5" to mean the same thing. I'm looking for something that would let me keep the form/validation duplication to a minimum.
What are the best ways to go about this with the model and the view?
The regular expression to allow both formats wouldn't be that complicated. I would perform that simple validation client-side via javascript. Beyond that, you may want to add some business validation (at the business object level) for this.
I used jQuery to create a slider that would change the time in the input box in the right format.
In my View File, Create.aspx, put the following jquery function somewhere in the beginning of the body.
<script>
$(function () {
$("#slider").slider({
value: 9,
min: 0,
max: 1440,
step: 15,
slide: function (event, ui) {
var hours = Math.floor(ui.value / 60);
var minutes = ui.value - (hours * 60);
var ampm = "AM";
if (hours == 12) { ampm = "PM"; }
else if (hours == 0) { hours = 12; ampm = "AM"; }
else if (hours > 12) { hours = hours - 12; ampm = "PM"; }
if (hours < 10) hours = '0' + hours;
if (minutes < 10) minutes = '0' + minutes;
$("#work_StartTime").val(hours + ':' + minutes + ' ' + ampm);
}
});
});
</script>
then down in the body of the same page put a div near the textbox for time input. A slider will show up at that div
<div class="editor-field">
<%: Html.EditorFor(model => model.work.StartTime)%>
<div id="slider"></div>
<%: Html.ValidationMessageFor(model => model.work.StartTime)%>
</div>
this will give you a slider. In the above javascript code change the step:15, makes increments to be 15 minutes.
This is obviously a client side validation. A server side validation should also be implemented of course.

Resources