XPath - find upcoming birthdays - xpath

How can I find contacts with upcoming birthdays, say within 10 days, given the following XML?
<contacts>
<contact>
<name>bob</name>
<birthday>1978-05-06</birthday>
</contact>
<contact>
<name>mary</name>
<birthday>1955-06-06</birthday>
</contact>
<contact>
<name>john</name>
<birthday>1998-05-06</birthday>
</contact>
</contacts>
I've got the following xpath but it breaks down because the month-from-dateTime returns an integer (5) instead of a '0' padded string (05). Is there a way to build a date in Xpath that will accept integer parameter for day, month, year instead of my ungly hack concatenating strings?
/contacts/contact[days-from-duration(xs:dateTime(concat(year-from-dateTime(current-date()),'-',month-from-dateTime(xs:dateTime(birthday)),'-',day-from-dateTime(xs:dateTime(birthday)))) - current-date()) < 10]

You can use a yearMonthDuration to add so enough years to move the date to the current year:
/contacts/contact[
xs:dateTime(birthday) + xs:yearMonthDuration("P1Y") * (year-from-dateTime(current-date()) - year-from-dateTime(xs:dateTime(birthday))) < current-date() + xs:dayTimeDuration("P10D")
]
And to check that the birthday is not in the past (for works like let to avoid typing it all twice here):
/contacts/contact[
for $thisYearBirthDay in xs:dateTime(birthday) + xs:yearMonthDuration("P1Y") * (year-from-dateTime(current-date()) - year-from-dateTime(xs:dateTime(birthday)))
return $thisYearBirthDay >= current-date() and $thisYearBirthDay < current-date() + xs:dayTimeDuration("P10D")
]
However, to actually make it work, you need to check the current and the next year, in case the current-date is around xmas, e.g.:
/contacts/contact[
exists((for $delta in (0, 1) return xs:dateTime(birthday) + xs:yearMonthDuration("P1Y") * ($delta + year-from-dateTime(current-date()) - year-from-dateTime(xs:dateTime(birthday))))[. >= current-date() and . < current-date() + xs:dayTimeDuration("P10D")])
]

Related

How to construct TSTZRANGE in rom-sql?

I can't find how to write this query in rom-sql. Is it possible to add plain sql to where?
It looks for announcements which do not intersect with requests.
announcements.when and requests.when are tstzrange columns in postgres.
SELECT "announcements".* FROM "announcements" WHERE (
(SELECT COUNT(requests.id)
FROM requests
WHERE requests.id IN (1,2,3) AND
(TSTZRANGE(lower(requests.when) - INTERVAL '1 HOUR', upper(requests.when) + INTERVAL '1 HOUR', '()') &&
TSTZRANGE(lower(announcements.when)), upper(announcements.when), '()') AND
requests.user_id = 42
) = 0
)
Check out the 'Advance Postgres support' section of the docs, http://api.rom-rb.org/rom-sql/ROM/SQL/Postgres/Types looks like there is support TsTzRange range('tstzrange', range_read_type(:tstzrange))
I found a solution to my problem.
Not sure if it's the right way in rom-sql.
I'll accept better answer if any appear.
Until that, here's my solution - Sequel.lit
In my case I defined a method in Announcements relation:
def available(user_id)
request_ids = requests.by_user_id(user_id).confirmed.pluck(:id)
# +- 1 hour around request is not available
# last argument '()' means "do not include boundaries"
request_when = "TSTZRANGE(
lower(requests.when) - INTERVAL '1 HOUR',
upper(requests.when) + INTERVAL '1 HOUR',
'()'
)"
announcement_when = "TSTZRANGE(lower(announcements.when), upper(announcements.when), '()')"
where(Sequel.lit(
"(SELECT COUNT(requests.id)
FROM requests
WHERE requests.id IN (:request_ids) AND
#{request_when} && #{announcement_when} AND
requests.user_id = :user_id) = 0",
user_id: user_id, request_ids: request_ids
))
end

boost log text_file_backend performance

I am using boost log and I choose the text_file_backend, but I got bad performance. No matter sync or async, the boost log has a low performance. About in 6 seconds, it wrote 30M data to log file.
Follow is my code snippet, anyone can help me?
typedef boost::log::sinks::asynchronous_sink<
boost::log::sinks::text_file_backend> TextSink;
boost::log::sources::severity_logger_mt<LogSev> logger_;
boost::shared_ptr<TextSink> report_sink_;
// initialize report_sink
boost::shared_ptr<sinks::text_file_backend> report_backend =
boost::make_shared<sinks::text_file_backend>(
keywords::file_name = target + "/" + file_name
+ ".report.log.%Y_%m_%d.%N",
keywords::rotation_size = file_size, keywords::time_based_rotation =
sinks::file::rotation_at_time_point(0, 0, 0),
keywords::auto_flush = false);
boost::shared_ptr<sinks::file::collector> report_collector = CreateCollector(
target, max_use_size / 2, min_free_size);
report_backend->set_file_collector(report_collector);
report_backend->scan_for_files();
// add sink: report_sink
report_sink_ = boost::make_shared<TextSink>(report_backend);
report_sink_->set_formatter(
expr::format("[%1%]" + sep + "[%2%]" + sep + "[%3%]" + sep + "%4%")
% expr::format_date_time<boost::posix_time::ptime>(
"TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
% expr::attr<LogSev>("Severity")
% expr::attr<attrs::current_thread_id::value_type>("ThreadID")
% expr::message);
report_sink_->set_filter(expr::attr<LogSev>("Severity") >= report);
logging::core::get()->add_sink(report_sink_);
logging::add_common_attributes();
BOOST_LOG_SEV(logger_, info) << "blabal...";
I think one performance issue about your implementation is about Timestamp. It needs a system-call to find Time. I encountered the same problem. So I turned to use date library. It returns UTC time very fast. Also check first answer of this question, However if you want Timestamp based on timezone, date library is slow. you should better define your timezone and add to UTC.
see the example:
#include "date.h"
#define MY_TIME std::chrono::hours(4) + std::chrono::minutes(30)
string timestamp = date::format("%F %T", std::chrono::system_clock::now() +
MY_TIME);

Excel VBA - Compare numbers in one column and remove the higher "neighbor" numbers

I have a list of numbers in one column (0.331, 0.332, 0.444, 0.445, 0.562, 0.986, 0.990, 0.993, 1.021, 1.022, ...) and I would like to remove the numbers really close (0.001 difference only) to get the following list: (0.331, 0.444, 0.562, 0.986, 0.990, 0.993, 1.021...) removing always the higher number.
Any ideas?
The list is obviously quite long, and I already removed the duplicate.
Now, I would like to remove the higher "neighbor" numbers, maybe not the right term, but I hope you understand my question.
Thanks,
JLuc01
For information, I finally did this bit of code which do the job.
' Remove close duplicate (with a difference of 0.001 only)
For i = 1 To Sheet2.Cells(Rows.Count, 1).End(xlUp).Row - 1
Sheet2.Cells(i + 1, 2).Value = Sheet2.Cells(i + 1, 1).Value - Sheet2.Cells(i, 1).Value
Next i
For i = 1 To Sheet2.Cells(Rows.Count, 2).End(xlUp).Row - 1
If Sheet2.Cells(i + 1, 2).Value < 0.002 Then
Sheet2.Cells(i + 1, 2).EntireRow.Delete
End If
Next i
Thank you for your help.
JLuc01

Retrieving time for microbenchmarking scripts with millisecond-level accuracy

I want to read a file using shell script and here want to calculate the time required to read a file. I have created below method to get the time in milliseconds at the start and end of the file reading and I will calculate the time difference, but it is not adding the hour+minute+seconds and showing me that the required numeric input.
Method
getCurrentTimeInMili()
{
hourTime=$(($(date +%H)*3600))
minuteTime=$(($(date +%m)*60))
secondTime=$(date +%S)
timeInMili= $(($hourTime + $minuteTime + $secondTime));
return timeInMili
}
Error
./testshell.sh: line 17: return: timeInMili: numeric argument required
omit the space between timeInMili= and $
timeInMili= $(($hourTime + $minuteTime + $secondTime));
^
This to
timeInMili=$(($hourTime + $minuteTime + $secondTime));
Invoking date multiple times means that their return values can be a bit out of sync with each other -- which could be bad if we're invoked just before a second boundary. Better is to call date only once and retrieve all the information desired, like so:
getCurrentTimeInMili() {
date +'%H 3600 * %M 60 * + %S + 1000 * %N 1000000 / + p' | dc
}
startTime=$(getCurrentTimeInMili)
sleep 5
endTime=$(getCurrentTimeInMili)
If you don't need this much accuracy, you can simply use the time builtin, as in:
time sleep 5

Date-time comparison in Ruby

I have one date, let's say '2010-12-20' of a flight departure, and two times, for instance, '23:30' and '02:15'.
The problem: I need to get datetimes (yyyy-MM-dd HH:mm:ss, for example, 2010-12-17 14:38:32) of both of these dates, but I don't know the day of the second time (it can be the same day as departure, or the next one).
I am looking for the best solution in Ruby on Rails. In PHP would just use string splitting multiple times, but I believe, that Rails as usually, has a much more elegant way.
So, here is my pseudo code, which I want to turn into Ruby:
depart_time = '23:30'
arrive_time = '02:15'
depart_date = '2010-12-20'
arrive_date = (arrive.hour < depart.hour and arrive.hour < 5) ? depart_date + 1 : depart_date
# Final results
depart = depart_date + ' ' + depart_time
arrive = arrive_date + ' ' + arrive_time
I want to find the best way to implement this in Ruby on Rails, instead of just playing with strings.
This is just pure Ruby, nothing to do with Rails:
require 'date'
depart_time = DateTime.strptime '23:30', '%H:%M'
arrive_time = DateTime.strptime '02:15', '%H:%M'
arrive_date = depart_date = Date.parse( '2010-12-20' )
arrive_date += 1 if arrive_time.hour < depart_time.hour and arrive_time.hour < 5
puts "#{depart_date} #{depart_time.strftime '%H:%M'}",
"#{arrive_date} #{arrive_time.strftime '%H:%M'}"
#=> 2010-12-20 23:30
#=> 2010-12-21 02:15

Resources