Why is the default of field "hour" in os.time 12? - time

The table parameter of os.time has three mandatory fields year, month and day, and may have fields hour (default is 12), min (default is 0), sec (default is 0), and isdst (default is nil).
The hour field seems a bit strange, why is it default to 12 instead of 0 like other fields?
I also note that it's documented in Lua 5.2 manual but not Lua 5.1 manual, but a little test show that it's true in both versions.
print((os.time{year=2014, month=5, day=13}) - (os.time{year=2014, month=5, day=13, hour=0}))
Output: 43200 (12 * 60 * 60)

Found the explanation by Roberto Ierusalimschy from here:
It was intentional. It is even documented in PiL (pg. 202, 2nd edition) (although not in the manual). I never realized that 'date' has a different default. (Noon seems to be more "inside" a given date than midnight...)

Related

Xpath/xQuery difference in months

I am trying to get the difference between two dates in months for an xPath.
I have no problems getting it in days (1127)
days-from-duration(xs:date('2012-06-17')-xs:date('2009-05-17'))
When I try doing it in months I get 0
months-from-duration(xs:date('2012-06-17')-xs:date('2009-05-17'))
I did notice that this comes back as days only ("P1126D") so that maybe the problem just not sure how to fix it.
xs:date('2012-06-17')-xs:date('2009-05-17')
Thanks for any help!
So the best thing I can seem to do is manually calculate it.
(year-from-date(xs:date('2012-06-17')) - year-from-date(xs:date('2012-05-18')))*12 + month-from-date(xs:date('2012-06-17')) -month-from-date(xs:date('2012-05-18')) + (if (day-from-date(xs:date('2012-06-17')) < day-from-date(xs:date('2012-05-18')) ) then -1 else 0)
This function was not included in the spec because we couldn't agree semantics for it. We heard arguments that the difference between 31 March 2015 and 30 Sept 2015 was six months, and arguments that it was five months. (Advice: negative differences seem to be even more problematic than positive differences.) You can easily find that a date plus 6 months minus 6 months is not the date where you started. You'll have to define what you think the answer should be, and implement it using lower-level facilities such as month-from-date and year-from-date.
The problem is that days-from-duration returns the days field -- not the number of days the duration includes. Likewise for months and years.
Now, you can divide by days, but not by months (since months have uneven boundaries):
(: arg1 here is a dayTimeDuration, which can't be easily converted to a yearMonthDuration :)
let $arg1 := xs:date('2012-06-17')-xs:date('2009-05-17')
return xs:dayTimeDuration($arg1) div xs:dayTimeDuration("P30D")

Why does Ruby think there are 366 days in 100 AD?

The following expression returns '366' in Ruby, implying 100 AD is a leap year (which it is not):
(Date.ordinal(101) - Date.ordinal(100)).to_i
Same with DateTime.
However, Date.leap?(100) correctly returns false.
Same results for version 1.9.1. and 2.0.0.
What gives? Should I file a bug report?
Update
Also, apparenly 1582 AD is 10 days short!
(Date.ordinal(1583) - Date.ordinal(1582)).to_i
=> 355
According to Wikipedia, 100 was indeed a leap year and 1582 did indeed skip 10 days.
Apparently, prior to 1582-10-15, Ruby interprets dates as Julian calendar dates, instead of Gregorian calendar dates. More details here:
http://teleologi.blogspot.com/2013/05/ruby-times-dates-good-bad-and-so-on.html
Apparently not a bug, but definitely violates the principle of least surprise (at least in the eyes of this coder).
How confusing!
Edit
Debate about "reasonable defaults" aside, Ruby seems to quite flexible on these touchy issues of calendar-choice, compared to other languages. I've learned that the Date and DateTime constructors can receive a "reform date" constant, which determines when the transition from Julian to Gregorian calendar occurs. The default is ITALY (1582-10-15), but ENGLAND is also an option (the jump occurs at 1752-09-14).
To avoid surprises from transitioning between calendars, I should have used the Gregorian calendar for all dates:
(Date.ordinal(i+1,1,Date::GREGORIAN) - Date.ordinal(i,1,Date::GREGORIAN)).to_i
=> 365
Also, Date.leap?(100) returned "false" because it is an alias of Date.gregorian_leap?. Meanwhile, Date.julian_leap(100) returns true. To avoid surprises, probably best to use method version of leap?, which uses whichever reform date you've picked.
Date.new(100, 1, 1, Date::JULIAN).leap?
=> true
Date.new(100, 1, 1, Date::GREGORIAN).leap?
=> false

Reading time values in Excelx in ruby

I am using 'roo' gem, to read and parse the xlsx file. The file contains a start_time, which may have the user input values in the format of 06:00 AM. When the file is uploaded, I am getting the parameters converted to Sat, 30 Dec 1899 or "1899-12-30". I am wondering whether in any way, we can get the actual time format, the user mentioned in the file or can we convert the available parameter, to the actual file cell value.
Or is there any format or validations for xlsx file cell.
Thanks in advance.
This got resolved, as I changed the excel cell format to Text.
I've found that the xlsx reading libraries in Ruby, including Roo, get dates wrong. This is unfortunate but understandable, since excel uses both 'type' xml attributes and formatting rules that are awkward at best, and user-generated at worst.
Still, with effort, it is possible to get right most if not all of the time, which is why I wrote simple_xml_reader. If possible, use it, otherwise your solution will be the most reliable, since by my experience trying to use the previously-existing Ruby gems, they will only get it right a fraction of the time, if at all.
Changing excel cell format to text is the option only if you want to convert/parse the excel file once. What if you want the permanent solution? here you go -
xlsx.excelx_value(row,col)
This will give you the time value as representation of day i.e.
0.25 = 06:00 AM
0.50 = 12:00 PM
0.75 = 18:00 PM
and so on
you just need to convert this to minutes i.e. 0.25 * 1440 = 360 minutes = 06:00
You can even convert that into seconds 0.25 * 1440 * 60 * 60 = 21600 seconds
and then
Time.at(seconds).strftime("%H:%M:%S")

Why is my YouTube API Insight report query 404ing?

I have a Ruby script which downloads YouTube Insight reports for specific videos within specific date ranges. It authorizes with ClientLogin, retrieves <entry> XML data for a video, and extracts from that data a URL which points to a CSV report:
http://insight.youtube.com/video-analytics/csvreports
?query={VIDEO_ID}
&type=v
&starttime=1315353600000
&endtime=1317772800000
&user_starttime=1317168000000
&user_endtime=1317772800000
&region=world
&token={API_TOKEN}
&hl=en_US
The above URL works. However, I want a report for a specific date range, not the default range provided.
An Insight report query's requested date range is set in the user_starttime and user_endtime params. (In the above default case, it's 2011-09-27 through 2011-10-04.) The YouTube API docs say that you can specify your own date range (covering a span of up to 28 days) by substituting timestamps (in milliseconds) that represent the dates you want.
So, why does the following query 404?
http://insight.youtube.com/video-analytics/csvreports
?query={VIDEO_ID}
&type=v
&starttime=1315353600000
&endtime=1317772800000
&user_starttime=1307937600000
&user_endtime=1308110400000
&region=world
&token={API_TOKEN}
&hl=en_US
The date range looks OK:
ruby > Time.at 1307937600
=> 2011-06-13 00:00:00 -0400
ruby > Time.at 1308110400
=> 2011-06-15 00:00:00 -0400
The fact that the "default" URL works indicates that I must be doing something wrong with these date values, but I can't figure out what. What am I overlooking?
UPDATE 2 -- Nov. 4, 2011:
There has recently been a change to the YouTube Data API Protocol for Insight data, and the answer below is no longer accurate.
YouTube now permits date ranges of up to 31 days for a single Insight report query, and they now allow requests pertaining to dates going back to March 1, 2009. The docs now say:
You can adjust the date range for which a report contains data
to a period of up to 31 days beginning no earlier than March 1, 2009.
This is excellent news. (Leaving the below for posterity.)
I believe I've figured out why the above Insight report query with the custom date range is 404ing. I was able to retrieve a report with a custom date range like this:
http://insight.youtube.com/video-analytics/csvreports
?query={VIDEO_ID}
&type=v
&starttime=1315353600000
&endtime=1317772800000
&user_starttime=1315627200000
&user_endtime=1315972800000
&region=world
&token={API_TOKEN}
&hl=en_US
What's the difference between this (good) URL and the previous (bad) URL in my question above? Well, my custom date range here, specified in the user_starttime and user_endtime parameters both fall within the range set by YouTube in the starttime and endtime params.
In other words, starttime and endtime seem to represent the outer bounds of any user-specified custom date range possible through these types of requests.
So, when the YouTube API docs say:
You can adjust the date range for which a report contains data to a period of up to 28 days
What they mean, I suppose, is:
Your date range may not span more than 28 days ... AND ALSO ...
Your date range may not fall outside of a date range going back 28 days from the most recent date on which reports are currently available, which we tell you through the starttime and endtime parameters.
UPDATE:
In this thread, a YouTube API Team member says:
You should consider the starttime value the absolute earliest supported start date and endtime the absolute latest supported end date. If you try to set user_starttime to something earlier than starttime then you're going to ask for data that dates back more than 28 days, and that data isn't available.
This exact text should be in the documentation.

Is there programmatical way to get short day names in windows?

Is there a way to get a 2 character day-name of the week such as MO/TU/WE/TH/FR/SA/SU?
Currently I only know of using FormatDateTime():
"ddd" returns "Fri"
"dddd" returns "Friday"
The main reason is that I want to obtain localized version of the 1 or 2 character day names:
Say FRIDAY in "ddd" would return:
French Windows = "Vendredi", the 2 char would be "VE", note it's the 1st and 2nd char.
Chinese Windows = "星期五", the char would be "五", note it's the 3rd char.
Japanese Windows = "金曜日", the char would be "金", note it's the 1st char.
Edit1:
Currently using Delphi, but i think applies to other languages too.
Edit2:
Simply put, I'm looking to obtain the shorter version of "ShortDayName" through the use of some functions or constants, so that I don't have to build a table of constants containing the 7 day "Shorter" day names for every possible windows language.
I wonder if such functions really exist.
Maybe the calendar 1 or 2 char day names in Outlook are hard-coded themselves, right?
You can get the local names for the days of the week with ShortDayNames and LongDayNames, and you can use DayOfWeek to get the numeric value for the day.
ShortDayNames[Index]; //Returns Fri
or
LongDayNames[Index]; //Returns Friday
The only way I know to shorten them to two chars would be to trim the resulting string
LeftStr(LongDayNames[Index],2);//Returns Fr
So today's Day would be
LeftStr(LongDayNames[DayOfWeek(date)],2); //Returns Fr
Click Here
Depicts the standards in custom date formatting.
You may also use the 'ddd' standard and trim it.
Delphi's routines does nothing special - they just ask OS.
Here is how to to it: Retrieving Time and Date Information. I looked through MSDNs docs and found this.
Note, that there is no really such thing as "2 character day-name" or "3 character day-name" here. There are: native ("long" in Delphi), abbreviated ("short" in Delphi) or short (Vista and above, not present in Delphi) formats.
For example, abbreviated name of the day of the week for Monday: Mon (3 chars, en-US), Пн (2 chars, ru-RU).
So, you probably look for LOCALE_SSHORTESTDAYNAMEX format (which is called "short" by MSDN and doesn't appear in Delphi), but it is availavle only on Vista and above.
For example, the following code:
const
LOCALE_SSHORTESTDAYNAME1 = $60;
procedure TForm1.Button1Click(Sender: TObject);
begin
SetThreadLocale($409);
ShowMessage(
GetLocaleStr(GetThreadLocale, LOCALE_SSHORTESTDAYNAME1, '') + #13#10 +
GetLocaleStr(GetThreadLocale, LOCALE_SABBREVDAYNAME1, '')
);
end;
will show you:
Mo
Mon
But doing this for Russian will output:
Пн
Пн
Hope my edits make answer more clear ;)

Resources