Having trouble with a simple problem. I have a string that does not include timezone information that I need to parse into a DateTime struct. I can get it as UTC, but not local:
let from = NaiveDateTime::parse_from_str(&start_date, "%Y-%m-%dT%H:%M:%S")?;
let from_utc = DateTime::<Utc>::from_utc(from, Utc);
You need Local.from_local_datetime() to convert a NaiveDateTime into a DateTime<Local>:
let from: NaiveDateTime = start_date.parse().unwrap();
let date_time = Local.from_local_datetime(&from).unwrap();
Admittedly, this isn't really easy to find in the documentation.
The first line you have works fine as well. For this particular format (RFC3339), it's easier to use str::parse(), though.
I have the following piece of code before me:
var testDate = 1481103000000;
var enterTime = moment(testDate, "x");
console.log(enterTime);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.js"></script>
The variable enterTime results in a momentjs object with an additional _f property set to "x" and a _pf property of type object (see the console log) compared to a normal moment(testDate) object.
I couldn't find information on the _f or _pf properties anywhere.
Can anyone tell me what the "x" stands for and for what reason it is being used?
Thanks in advance.
With moment(testDate, "x"); you are creating a moment object using moment(String, String); function specifying x as format (Unix ms timestamp).
When you do moment(testDate), you are creating a moment object using moment(Number);.
All moment properties starting with _ are for internal use, _f stands for format, while _pf stand for Parsing Flags.
You can have a look to moment code to get more details about _f and _pf.
x denotes Unix ms timestamp
Please note that this parameter is case-sensitive:
X Output: 1410715640.579 Unix timestamp
x Output: 1410715640579 Unix ms timestamp
Refer here for all the options.
I am trying to build the inline segment to filter the pages (ex. to separate the pages for blogs and games) using the function BuildClassificationValueSegment() to get the data from Adobe Analytics API,
I have tried some thing like
report.data.visits <- QueueTrended(reportsuite.id,date.from,date.to,metrics,elements,
segment.inline = BuildClassificationValueSegment("evar2","blog","OR")).
Got error like :
Error in ApiRequest(body = report.description, func.name = "Report.Validate") :
ERROR: segment_invalid - Segment "evar2" not valid for this company
In addition: Warning message:
In if (segment.inline != "") { :
the condition has length > 1 and only the first element will be used
Please help on the same.Thanks in advance...
I recommend you to declare the InlineSegment in advance and store it in a variable. Then pass it to the QueueTrended function.
I've been using the following syntax to generate an inline segment:
InlineSegment <- list(container=list(type=unbox("hits"),
rules=data.frame(
name=c("Page Name(eVar48)"),
element=c("evar48"),
operator=c("equals"),
value=c(as.character("value1","value2"))
))
You can change the name and element arguments in order to personalize the query.
The next step is to pass the InlineSegment to the QueueRanked function:
Report <- as.data.frame(QueueRanked("reportsuite",
date.from = dateStart,
date.to = dateEnd,
metrics = c("pageviews"),
elements = c("element"),
segment.inline = InlineSegment,
max.attempts=500))
I borrowed that syntax from this thread some time ago: https://github.com/randyzwitch/RSiteCatalyst/issues/129
Please note that there might be easier ways to obtain this kind of report without using InlineSegmentation. Maybe you can use the selected argument from the QueueRanked function in order to narrow down the scope of the report.
Also, I'm purposefully avoiding the BuildClassificationValueSegment function as I found it a bit difficult to understand.
Hope this workaround helps...
Unless I use the .toLocaleDateString() method, the function below returns a date that is one day less than it should be. Am I doing something wrong or is this a defect?
function myDate() {
var sDate = '05/10/2012';
var parts = sDate.split('/');
var d = new Date( parts[2], parts[1]-1, parts[0]);
Logger.log(d);
Logger.log(d.toLocaleDateString());
};
The Logger returns:
Thu Oct 04 16:00:00 PDT 2012
05 October 2012 00:00:00 BST
I'm in the UK, hence the UK date format. I've checked that my project properties have the time zone set to "(GMT+00:00) London" so why does the Logger show the first date in PDT? Is that the reason for the wrong date? I've reproduced the problem in a stand-alone project. Here's a link to it.
I wanted to convert the string variable into a date object in order to do some date math so having to convert back to a string with .toLocaleDateString() method isn't helpful.
I've checked for consistence, thinking perhaps I could work around it, by testing with other dates. Bizarrely, if I change the value of sDate to anything between 01/01/2012 & 04/03/2012 it returns accurately. From 05/03/2012 onwards it drops a day. With 2013 dates, it returns correctly until 29/04/2013 when it starts dropping a day again. So it's not consistent. It seems similar to the problem reported here.
I found that dates read by the getValues() function on a range that were between the old DST rules and the new DST rules were decremented by 1 hour. So, the implicit time for the date "10/30/2012" is 00:00:00. But, when read in, it was decrementing by an hour, landing it in the previous day, i.e. 10/29/2012 23:00:00.
Any date between these two timeframes, not inclusive of the start day but inclusive of the end day, will exhibit this behavior currently, at least as read by the getValues() function:
Between the last Sunday in October and the first Sunday in November
Between the second Sunday in March and first Sunday in April.
I ended up writing code that would dynamically calculate these dates for the current year and if the date landed in the target range, I would simply increment it by an hour. This may be the the long way to fix it, but it works.
Here is my code:
/*
The old rules for DST stated that the time change occurred on the last Sunday in October,
which would be 10/28/2012. So, when you type in 10/29/2012, the timestamp associated with the date (00:00:00) is being decremented by an hour (23:00:00),
which drops it into the previous day. The new rules for DST states that DST ends on the 1st Sunday in November, which is 11/04/2012. Also, the DST rules
for springtime are also an impacted range of dates that exhibit this behavior, between the second sunday in March and the first sunday in April.
Note: Running this function from the script editor does not produce the strange DST behavior. It seems to be an issue with the getValues() function on a Range object.
*/
function fixDateDSTProblem(lstrDate){
var d = new Date(lstrDate);
//Example ranges affected
//10/29/2012 - 11/04/2012
//03/11/2013 - 04/07/2013
if(isNaN(d.getMonth())){
//return what was passed in if it's not a date or null.
return lstrDate;
}
else if(isAffectedDate(d)){
//increment by one hour
return new Date(d.getTime() + (60 * 60 * 1000));
}
else{
//date is not affected, simply return it as it was passed.
return lstrDate;
}
}
//Check to see if a date is within a beginning and end date
function dateWithin(beginDate,endDate,checkDate) {
var b,e,c;
b = Date.parse(beginDate);
e = Date.parse(endDate);
c = Date.parse(checkDate);
//slightly modified this for the date checking since beginning date is not inclusive, so needs to be > instead of >=
if((c <= e && c > b)) {
return true;
}
return false;
}
function isAffectedDate(targetDate){
var yearNum = targetDate.getFullYear();
//Get the last Sunday in October
var lastSunOctDateStr = getLastOccurrenceDate(0, 10, yearNum);
//Get the first Sunday in November
var firstSunNovDateStr = getOccurrenceDate(1, 0, 11, yearNum);
//Get the second Sunday in March
var secondSunMarDateStr = getOccurrenceDate(2, 0, 3, yearNum);
//Get the first Sunday in April
var firstSunAprDateStr = getOccurrenceDate(1, 0, 4, yearNum);
//if the date is between the last sunday in october and the first sunday in november
// or if the date is between the second sunday in march and the first sunday and april, fix it up!
if(dateWithin(lastSunOctDateStr, firstSunNovDateStr, targetDate) ||
dateWithin(secondSunMarDateStr, firstSunAprDateStr, targetDate)){
return true;
}
return false;
}
function getOccurrenceDate(numOccurrence, dayIndex, monthCalendar, yearNum){
//"Get date of first occurrence of Monday in June 2013"
//"Get date of the second occurrence of Sunday in April 2013"
//dayIndex: Sunday = 0, Saturday = 6
var monthIndex = monthCalendar - 1;
var numFirstXDay = null;
var firstDay = new Date(monthCalendar+"/01/"+yearNum);
var numDayOfWeek = firstDay.getDay();
if(numDayOfWeek == dayIndex){
numFirstXDay = 1;
}
else if(numDayOfWeek > dayIndex){
numFirstXDay = 1+(6-numDayOfWeek)+1+dayIndex+(7*(numOccurrence-1));
}
else if(numDayOfWeek < dayIndex){
numFirstXDay = 1+(dayIndex - numDayOfWeek)+(7*(numOccurrence-1));
}
return monthCalendar+"/"+numFirstXDay+"/"+yearNum;
}
function getLastOccurrenceDate(dayIndex, monthCalendar, yearNum){
//Example: "Get date of last occurrence of Monday in June 2013"
var monthIndex = monthCalendar - 1;
var numLastXDay = null;
//TODO: Handle Leap Year!
var monthMaxDaysArray = {
'1':'31',
'2':'28',
'3':'31',
'4':'30',
'5':'31',
'6':'30',
'7':'31',
'8':'31',
'9':'30',
'10':'31',
'11':'30',
'12':'31'}
var lastDay = new Date(monthCalendar + "/"+monthMaxDaysArray[monthCalendar]+"/" + yearNum);
var numDayOfWeek = lastDay.getDay();
if(numDayOfWeek == dayIndex){
numLastXDay = 31;
}
else if(numDayOfWeek > dayIndex){
numLastXDay = monthMaxDaysArray[monthCalendar] - (numDayOfWeek - dayIndex);
}
else if(numDayOfWeek < dayIndex){
numLastXDay = (monthMaxDaysArray[monthCalendar] - numDayOfWeek) - (6 - (dayIndex-1));
}
return monthCalendar + "/" + numLastXDay + "/" + yearNum;
}
The logger always logs dates in PDT. It's the same instance of time, just represented a different way. You are seeing that + differences in daylight savings time.
Even if Corey's answer doesn't need any confirmation (he knows what he is talking about ;) let me add some practical details ...
every javascript manipulation you do on date object (getDay, getTime, getFulYear...) will return correct values even if the logger value you see seems wrong so you don't need to convert to string and back to numbers if you need to manipulate dates
If these dates are shown in a spreadsheet then the spreadsheet locale settings will be used to show the desired values.
Sometimes you will see the values in other format in the logger... don't ask when or why but it happens to me sometimes (I'm in GMT+1 Belgium)
The date shift you notice in october and april are indeed happening when daylight savings starts and stops and this can become tricky when you need to define a date in a calendar event in one period from another (for example today I create an event in december there will be 1 hour difference) so you need to use the right GMT+0X00 value when you read a date object in a user interface using utilities.formatDate
If for some reason you show a list of dates starting before daylight savings switch day and ending after, and you use utilities.formatDate, it is better to user a variable to play with 'GMT+0X00' dynamically : I get it simply using something like this :
* EDIT* since a few weeks the syntax has changed and this string has to be formated differently, so I updated this code accordingly. (see issue 2204)
`var FUS1=new Date().toString().substr(25,6)+":00";// FUS1 gets the GMT+02:00 or GMT+01:00 string`
Hoping it's getting clear enough
Sorry to join the party a few months late...
The problem with these answers is that none of them actually make it clear that this is a BUG. Or, to be more precise, this is something that Google have decided is "correct" behaviour (see Issue 1271, for example, closed with no action), when it quite clearly is completely the wrong thing to do.
Consider this. I want to put someone's birthdate in a spreadsheet, and I have a large list of them. I then want to read out the value and put it in a form:
function getAge(ss, index) {
var ages = ss.getRangeByName("birthDates").getValues();
return ages[index];
}
...
app.createLabel(getAge(ss, index));
The form now contains the wrong birthdate for everyone born between April and October. Google has decided that they were actually born one day earlier. Or try to read out the ages, and put them in another spreadsheet, with no processing, where both spreadsheets have the same time zone setting. Same story, and it leaves me looking really stupid when people mail to tell me that I've got their birthdates wrong.
This is how it should be done: if someone manually specifies a date, for example "06/06/1997", then reads that date with getValue, they expect to get "06/06/1997" back, not the day before. They really don't expect you to try to second guess them: "Ok, this date happens to be during DST, so what they really expect to read back from getValue is something corrected to non-DST, so why don't we subtract an hour and give them the day before?"
It's crazy. If Excel did that, it would be a laughing stock. Fix it, please.
EDIT
Serge, that's very interesting, but your spreadsheet shows a work-around which extracts a TZ, and then displays according to that TZ. But that just avoids the issue that this is wrong to start with. Consider this. Spreadsheets almost invariably contain anniversaries of fixed dates - someone's birthday, the date of a battle, the time/date of an appointment, whatever. These are independent of TZ. If your birthday is 6th July 1960 in Belgium, then it's also 6th July if you happen to live in California. If you were born at 00:30AM, your passport still shows 6th July, even though that time was actually 5th July in CET and PDT. For an anniversary, or an appointment, no-one gives a damn about timezones. In a spreadsheet, only a tiny proportion of users care about TZ's. I can't immediately think of a single use-case where it actually matters.
Lotus 1-2-3 got this right. Excel got this right. A date is an integer serial number, with no time zone information. Copy a date from one spreadsheet to another, it's always right. Get a date from a spreadsheet using VB/whatever, put it in another spreadsheet, it's always right (I think). Much as I hate to say it, Excel defines spreadsheets, and they do it Good. Apart from VB.
In GAS, if I copy a date using getValues, it's wrong. Google have over-smarted this. Ok, there is a complex work-around that involves finding what TZ your spreadsheet was created in, assuming that the date you entered was actually an epoch date relative to UTC, and displaying it according to the spreadsheet's current TZ setting (at least, I think that's what you're doing). But so what? And, does it always work? What if you mail the spreadsheet to someone who lives in PDT? I'm sure you can get it to work, but that misses the point - this is just a work-around, which I think might be fragile (note that there are 3 TZ settings: the Google account setting, the sheet setting, and the script setting, and you have to take account of all of them - see ahab's post here). The fundamental issue is that Google spreadsheets store dates relative to a specific TZ (is the underlying format ms relative to Unix epoch??). This was just wrong, and is now unfixable, and is only one part of a large can of worms to do with date handling.
As a short-term fix, I can probably add 12 hours to all dates in a spreadsheet. As a longer-term fix, I should probably handle all dates as text strings and do it myself in JavaScript. I've already had to replace all elapsed times with "integral" number of milliseconds to handle the issues to do with lost milliseconds in GAS dates. Go on, convince me I'm wrong.
EDIT by Serge :
Hi, I took the liberty to answer in your edit for ease of reading (sorry about that).
I do understand your point of view but I don't share it.
The UI example you refer to needs indeed a workaround because this is pure javascript, not spreadsheet date ... That said, Excel spreadsheets and Google spreadsheets work the same way (next day is day+1, time = decimals and ref date 0 = 12/31/1899)) as long as you stay in the spreadsheet universe, the problem comes when you quit the spreadsheet and go to Javascript (ref date = 01/01/1970, count in milliSecs)...
If they had chosen not to care about TZ and keep dates 'static' across any time zone it would have had a lot of other issues : for example what if you want to setup an appointment on skype between me in Belgium and President Obama in Washington ? If we decide to have that conversation on monday at 8 AM will it be 8 AM in Belgium or in Washington ?
With the Google solution he will just have to wake up a bit early but we will both be there since the date and time would show the same 'moment', with the way you suggest there won't be any chance we talk to each other (how sad that would be^^) .
There are a lot more situation where it is obviously a better choice : communication with Calendar service is also a good example.
The static excel solution works nicely because such a document isn't shared the same way and doesn't convert dates to Javascript date Objects. An Excel SS is related to the computer's user, a Google SS keeps this relation to the user's computer using the Time Zone setting because it is (by nature) not related to user's computer.
I have little hope to convince you (;-) but I hope this will at least make things a bit clearer... (and anyway I'm not a Google engineer and have no way to influence them in any way ^^).
one more EDIT...
Here is a small test sheet with TZ settings set to GMT-8 that gets the value of the other test sheet (set to GMT+2 Belgian winter time) and shows it the right way by using this simple script :
function timeCorrection() {
var thisSheet = SpreadsheetApp.getActiveSheet();
var otherSS = SpreadsheetApp.openById('0AnqSFd3iikE3dENrc2h1M0ktQTlSNWpNUi1TS0lrNlE');
var otherSheet = otherSS.getSheetByName('Sheet1');
var otherValue = otherSheet.getRange(1,1).getValue();
var tz = otherSS.getSpreadsheetTimeZone();
var thisSheetValue = new Date(Utilities.formatDate(otherValue,tz,'MM/dd/yyyy HH:mm:ss'));
thisSheet.getRange(1,1).setValue(thisSheetValue);
}
As simple as that ;-) , settings of the 'foreign sheet' are set to the same value as its script settings which is default for a newly created sheet created in Vancouver.
This is not a bug...
May I offer another solution to the problem that is less programmatic? I isolated this issue and spend a day trying to figure out why my script was pulling dates with a previous day and 23:00PM.
Then, I realized that Spreadsheet is not a comma separated database but has its auto-formatting. So, the problem is solved when in Spreadsheet I selected my column containing dates and from menu chose Format>Numbers>Plain Text. Now my script runs perfect without tons of way around. Applying this to an entire column affects even a newly added cells. So its a sweet solution.
Since this is stackoverflow, here is the java solution (I check it works):
sheet.getRange(1,n).setNumberFormat('#STRING#');
I took it from christian.simms, from here:
Format a Google Sheets cell in plaintext via Apps Script
The main problem is incorrect time zone for a date object.
So I not found way to get a string from a cell if it has date type. The cell will return representation based on the time zone but it is not the same as on local computer, so you can get date ± one day.
You can get the time zone for the current account:
var userTimeZone = CalendarApp.getDefaultCalendar().getTimeZone();
Warning! This is not time zone of local computer, so this is another problem.
So you can get correct string of the date:
var date1 = SpreadsheetApp.getActiveSheet().getRange(1, 1).getValue();
var str = date1.toLocaleString("en-US", {timeZone: userTimeZone });