I'm new to App Script, please be gentle!
I have a table with a start date and a number of months, I need to list each recurring month from the start date to the number of months.
I'm struggling with 2 issues:
The first date placed in the array seems to be updating as I cycle the dates
The formats are in UNIX and I can't get them to be useful despite an awful lot of reading!
Thank you so much for any help!
Input file (https://i.stack.imgur.com/2EJ65.png)
Output file(https://i.stack.imgur.com/0DH5R.png)
Console log (https://i.stack.imgur.com/NVqck.png)
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Get Data sheet
var rawData = ss.getSheetByName('Sheet3');
// Get a date and set it as a date format
var start = new Date(rawData.getRange("B2").getValues());
console.log(start);
// Get Months
var months = rawData.getRange("C2").getValues();
// Define dates array
var dates = [];
// Add first date
const startDate = start
dates.push([startDate]);
//Add rest of dates dates in a loop
for (var run = 1;run < months;run++) {
//get the last pasted month name
var lastMonth = start.getMonth();
//push next month
dates.push([start.setMonth(lastMonth+1)]);
}
// Get processedData sheet
var processedData = ss.getSheetByName('sheet2');
// Post the outputArray to the sheet in a single call
console.log(start);
console.log(startDate);
console.log(dates);
console.log(dates.length);
console.log(dates[0].length);
processedData.getRange(1,1,6,1).setValues(dates);
}
Incrementing Dates by month and setting format
function lfunko() {
const ss = SpreadsheetApp.getActive();
let dt = new Date();
let start = new Date(dt.getFullYear(),dt.getMonth(),dt.getDate());//need to change back to your value
const months = 10;//need to change back to your value
let dates = [];
dates.push([start]);
for (let run = 1; run < months; run++) {
dates.push([new Date(start.getFullYear(),start.getMonth() + run, start.getDate())])
}
ss.getSheetByName('Sheet0').getRange(1, 1, dates.length).setValues(dates).setNumberFormat("mm/dd/yyyy");//changed sheet name
Logger.log(dates);
}
I have created an Apps Script to compile data and save the results to a new Google Sheet.
The code gets the current date with new Date() and uses that for the query and to name the new sheet it creates.
Here is the relevant part of the code:
function exportPayroll(setDate){
var date = new Date();
var newWeek = Utilities.formatDate(_getSunday(date),"GMT", "MM/dd/yyyy");
for (var company in companies){
getPayroll(companies[company],newWeek);
}
}
function _getSunday(d) {
d = new Date(d);
var day = d.getDay(),
diff = d.getDate() - day + (day == 0 ? -7:0); // adjust when day is sunday
return new Date(d.setDate(diff));
}
If I run exportPayroll manually, I get the exact results that I expect. So, I setup this trigger to automate the process:
When the trigger runs, the date value is 12/31/1969 instead of today.
Why does it act different with the trigger? Checking the execution transcript, I don't see any error messages.
Is there a better way to get today's date via a trigger?
Since you just wan't to get the Date of the previous sunday. Try running it this way.
function getLastSunday() {
var d = new Date();
var day = d.getDay();
var diff = d.getDate() - day + (day == 0 ? -7:0); // adjust when day is sunday
return new Date(d.setDate(diff));
}
function exportPayroll(){
var newWeek = Utilities.formatDate(getLastSunday(),"GMT", "MM/dd/yyyy");
for (var company in companies){
getPayroll(companies[company],newWeek);
}
}
I'm new to Protractor and here I'm trying to test an angularjs date picker from Protractor.
I tried to find a way to do this and this article was the only thing I found and It is not very clear to use
If someone know how to test please help.
What I need is to select today's date.
Thanks in advance :)
edit -
alecxe, here is the screen shot of my date picker. Unfortunately cannot provide the link of the page. :(
<input
class="form-control ng-pristine ng-valid ng-not-empty ng-touched"
ng-model="invoice.fromdate"
data-date-format="yyyy-MM-dd"
data-date-type="string"
data-max-="" data-autoclose="1"
bs-datepicker=""
ng-change="dateRange()"
type="text">
I think you can avoid manipulating the datepicker manually and instead set the date either by just sending the keys with a today's date value:
var picker = element(by.model("invoice.fromdate"));
// get today's date
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();
if(dd<10) {
dd='0'+dd
}
if(mm<10) {
mm='0'+mm
}
today = mm+'/'+dd+'/'+yyyy;
picker.clear();
picker.sendKeys(today);
Or, by setting the associated model's value directly:
picker.evaluate("invoice.fromdate= '" + today + "'");
Two methods have been suggested so far: 1. sendKeys() 2. evaluate()
I'm a bit new to protractor but I think both of these have issues in the case of not having an input element that spawns the calendar, i.e.:
Sendkeys() works only if date is on an element and the uib-datepicker is a dropdown sort of deal. This didn't help me because my datepicker element is a standalone and isn't paired with an input element.
evaluate() doesn't update angular's actual model in the browser (which begs the question of how useful evaluate actually is...). According protractor docs, evaluate, "Evaluates the input as if it were on the scope of the current underlying elements." In my case I want to test whether the date generated by the datepicker gets to my enpdpoint via a post request and then back again (hence e2e) without getting effed (corrupted), therefore, I need my date to be on my angular model in the browser instance, not just in the browser-driver environment or whatever the runtime environment of the protractor test is. I could be wrong about this.
This expect() passes but the ng-form is invalid (i'm assuming b/c model in browser wan't actually updated to receive the date I'm trying to pass in.):
function convertToPickerDate(date) {
var date = new Date(date);
var dd = date.getDate();
var mm = date.getMonth() + 1; //January is 0!
var yyyy = date.getFullYear();
var yy = yyyy.toString().slice(2);
return mm + '/' + dd + '/' + yy;
}
// expect passes, but form is invalid - DON'T USE for standalone cal
it('should enter start date in date picker', function () {
offerStart = convertToPickerDate(myData.startDate);
var offerStartPicker = element(by.model('current.startDate'));
offerStartPicker.evaluate("current.startDate = '" + offerStart + "'");
offerStartPicker.evaluate("current.startDate").then(function (value) {
expect(value).toBe(offerStart);
});
})
but the ng-form that the element is on is invalid...
My solution uses css selection and arrow keys to select a date relative to today:
Shipment Start Date: <em id="offerStartPrint">{{current.startDate | date:'shortDate' }}</em>
<div id="offerStart"
name="offerStart"
uib-datepicker
ng-model="current.startDate"
class=""
ng-change="setStartDate()"
datepicker-options="startDateOptions"
required></div>
</div>
function convertToPickerDate(date) {
var date = new Date(date);
var dd = date.getDate();
var mm = date.getMonth() + 1; //January is 0!
var yyyy = date.getFullYear();
var yy = yyyy.toString().slice(2);
return mm + '/' + dd + '/' + yy;
}
it('should enter expiration date in date picker using tabs and arrows :)', function () {
// select today element on uib-datepicker calendar
// div#offerStart elem has date model
var calToday = element(by.css('div#offerStart table td button.active'));
calToday.sendKeys(protractor.Key.ARROW_DOWN); // one week away
calToday.sendKeys(protractor.Key.ARROW_DOWN); // two weeks away
calToday.click(); // if you remove this click no date is entered
var fortnightAway = new Date(Date.now() + 12096e5);
fortnightAwayString = convertToPickerDate(fortnightAway);
expect(element(by.id('offerStartPrint')).getText()).toBe(fortnightAwayString);
})
Left and right arrows can be used to increment/decrement date by one day at a time.
up/down arrows can be used to inc/dec one week at a time.
One could probably figure out how to arrow through months and years as well.
var data_picker = element(by.model("invoice.fromdate"));
// select current date with date function
var current_date = new Date();
var day = today.getDate();
var month = today.getMonth()+1; //By default January count as 0
var year = today.getFullYear();
if(day<10) {
day='0'+day
}
if(month<10) {
month='0'+month
}
current_date = month+'/'+day+'/'+year;
data_picker.clear(); // Note if you are facing error message related to clear. Comment this line
data_picker.sendKeys(today);
Hope this will work
I am searching for a way to redirect to a url based on fixed time when the time (system or server) hits 06:00 o'clock it needs to redirect to given url.. it needs to check the time (system or server) every second i dont know if this is possible..?
You could do this by using javascript. I made an example. This checks the current hour and if it is between start and end it does something. you could trigger timeRedirect(); at document load or something.
<script>
function returnTime() {
var d = new Date();
var time = d.getHours();
console.log(time);
return time;
}
function timeRedirect() {
var start = 6;
var end = 22;
var time = returnTime();
if (time >= start && time <= end) {
console.log("redirect");
}
}
</script>
and for the redirect you could use this javascript, place it where the console.log(redirect) is.
window.location.replace("http://stackoverflow.com");
I am in the process of building a temporal expression library that must be properly globalized and therefore work in all available Time Zones.
Now I seem to be stuck as I'm not sure how to retrieve adjusted dates from DateTimeOffset objects in the correct Daylight Savings Time (DST) when the transition boundary is crossed using any variety of .Add to move days, hours, etc.
Interestingly, I figured out a work around for the local system's Time Zone but haven't found any way to apply the same strategy to any arbitrary Time Zone.
I was able to find a snippet (didn't keep source, sorry!) which tries to reverse lookup the Time Zone Info by offset but as there are multiple potential results, each of which likely have different DST rules that will not work. (There may be some optimizations available but the base premis is flawed I think)
public TimeZoneInfo GetTimeZoneInfo(DateTimeOffset Value)
{
// Search available sytem time zones for a matching one
foreach (var tzi in TimeZoneInfo.GetSystemTimeZones())
{
// Compare value offset with time zone offset
if (tzi.GetUtcOffset(Value).Equals(Value.Offset))
{
return tzi;
}
}
}
This stuff can be a bit tedious to prove out so I've extracted the core issue into a couple methods and unit tests which will hopefully demonstrate the issue I'm facing.
public DateTimeOffset GetNextDay_Wrong(DateTimeOffset FromDateTimeOffset)
{
// Cannot create a new DateTimeOffset using simply the supplied value's UtcOffset
// because in PST, for example, it could be -7 or -8 depending on DST
return new DateTimeOffset(FromDateTimeOffset.Date.AddDays(1), FromDateTimeOffset.Offset);
}
[TestMethod]
public void GetNextDay_WrongTest()
{
var tz = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var workingDate = new DateTime(2009, 11, 2, 0, 0, 0);
var failingDate = new DateTime(2009, 11, 1, 0, 0, 0);
var workingDate_tz = new DateTimeOffset(workingDate, tz.GetUtcOffset(workingDate));
var failingDate_tz = new DateTimeOffset(failingDate, tz.GetUtcOffset(failingDate));
var actual_workingDate_tz = GetNextDay_Wrong(workingDate_tz);
var actual_failingDate_tz = GetNextDay_Wrong(failingDate_tz);
var expected_workingDate = new DateTime(2009, 11, 3, 0, 0, 0);
var expected_failingDate = new DateTime(2009, 11, 2, 0, 0, 0);
var expected_workingDate_tz = new DateTimeOffset(expected_workingDate, tz.GetUtcOffset(expected_workingDate));
var expected_failingDate_tz = new DateTimeOffset(expected_failingDate, tz.GetUtcOffset(expected_failingDate));
Assert.AreEqual(expected_workingDate_tz, actual_workingDate_tz, "Should have found the following day's midnight");
Assert.AreEqual(expected_failingDate_tz, actual_failingDate_tz, "Failing date does not have the correct offset for it's DST");
}
public DateTimeOffset GetNextDay_LooksRight(DateTimeOffset FromDateTimeOffset)
{
// Because we cannot create a new DateTimeOffset we simply adjust the one provided!
var temp = FromDateTimeOffset;
// Move back to midnight of the current day
temp = temp.Subtract(new TimeSpan(temp.Hour, temp.Minute, temp.Second));
// Now move to the next day
temp = temp.AddDays(1);
// Let the DateTimeOffset class do it's magic
temp = temp.ToLocalTime();
// Check if the time zone has changed
if (FromDateTimeOffset.Offset != temp.Offset)
{
// Calculate the change amount (could be 30 mins or even stranger)
var delta = FromDateTimeOffset.Offset - temp.Offset;
// Adjust the temp value by the delta
temp = temp.Add(delta);
}
return temp.ToLocalTime();
}
[TestMethod]
public void GetNextDay_LooksRightTest()
{
// Everything is looking good and the test passes now, so we're home free yeah?
// { To work this needs to match your system's configured Local Time Zone, I'm in PST }
var tz = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
var workingDate = new DateTime(2009, 11, 2, 0, 0, 0);
var failingDate = new DateTime(2009, 11, 1, 0, 0, 0);
var workingDate_tz = new DateTimeOffset(workingDate, tz.GetUtcOffset(workingDate));
var failingDate_tz = new DateTimeOffset(failingDate, tz.GetUtcOffset(failingDate));
var actual_workingDate_tz = GetNextDay_LooksRight(workingDate_tz);
var actual_failingDate_tz = GetNextDay_LooksRight(failingDate_tz);
var expected_workingDate = new DateTime(2009, 11, 3, 0, 0, 0);
var expected_failingDate = new DateTime(2009, 11, 2, 0, 0, 0);
var expected_workingDate_tz = new DateTimeOffset(expected_workingDate, tz.GetUtcOffset(expected_workingDate));
var expected_failingDate_tz = new DateTimeOffset(expected_failingDate, tz.GetUtcOffset(expected_failingDate));
Assert.AreEqual(expected_workingDate_tz, actual_workingDate_tz, "Should have found the following day's midnight");
Assert.AreEqual(expected_failingDate_tz, actual_failingDate_tz, "Failing date does not have the correct offset for it's DST");
}
[TestMethod]
public void GetNextDay_LooksRight_FAILTest()
{
// Here is where the frustrating part is... aparantly the "magic" that DateTimeOffset provides only works for your systems Local Time Zone...
// { To properly fail this cannot match your system's configured Local Time Zone, I'm in PST so I use EST }
var tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var workingDate = new DateTime(2009, 11, 2, 0, 0, 0);
var failingDate = new DateTime(2009, 11, 1, 0, 0, 0);
var workingDate_tz = new DateTimeOffset(workingDate, tz.GetUtcOffset(workingDate));
var failingDate_tz = new DateTimeOffset(failingDate, tz.GetUtcOffset(failingDate));
var actual_workingDate_tz = GetNextDay_LooksRight(workingDate_tz);
var actual_failingDate_tz = GetNextDay_LooksRight(failingDate_tz);
var expected_workingDate = new DateTime(2009, 11, 3, 0, 0, 0);
var expected_failingDate = new DateTime(2009, 11, 2, 0, 0, 0);
var expected_workingDate_tz = new DateTimeOffset(expected_workingDate, tz.GetUtcOffset(expected_workingDate));
var expected_failingDate_tz = new DateTimeOffset(expected_failingDate, tz.GetUtcOffset(expected_failingDate));
Assert.AreEqual(expected_workingDate_tz, actual_workingDate_tz, "Should have found the following day's midnight");
Assert.AreEqual(expected_failingDate_tz, actual_failingDate_tz, "Failing date does not have the correct offset for it's DST");
}
The underlying issue with this case is that there is not enough information to perform the appropriate Time Zone conversions. Simple offset is not specific enough to infer the Time Zone because for a given offset at a specific moment there can be multiple potential Time Zones. Because the DateTimeOffset object does not capture and maintain the information about the Time Zone it was created with it must be the responsibility of something external to that class to maintain this relationship.
The thing that threw me off the scent was the call ToLocalTime() which I later realized was in fact introducing an implied TimeZoneInfo into the calculation, that of the configured local time for the machine and I believe that internally the DateTimeOffset must be converting to UTC by simply removing the configured offset and then creating a new DateTimeOffset class using the constructor taking DateTime [in UTC] and TimeZoneInfo [from local system] to produce the correct dst aware resulting date.
Given this limitation I no longer see any value in the DateTimeOffset class over the equally accurate and more valuable combination of DateTime and TimeZoneInfo.