In Rails, how to calculate durations between 2 UTC times read from mysql - mysql

I am using Rails 4. I've read 2 records(b1 and b2) from database. Both them have a column called build_start_time, which is defined as datetime type in Mysql. The build_start_time between b1 record and b2 record are like this:
2.0.0-p643 :021 > b1.build_start_time
=> Tue, 12 Aug 2014 18:23:31 UTC +00:00
2.0.0-p643 :012 > b2.build_start_time
=> Fri, 15 Aug 2014 10:07:18 UTC +00:00
How do I calculate the duration between them in Rails ? Does anybody have an idea?
The result should be something like:
b2.build_start_time - b1.build_start_time = 2 days 15 hours 53 minutes 47 seconds
Is this possible?

Assuming you can tolerate your answer being off by less than a second you could try using the to_i and ago methods:
def datetime_diff(datetime1, datetime2)
res = datetime1 <=> datetime2
if res == 0
# order doesn't matter in this case
min = datetime1
max = datetime2
elif res < 0
min = datetime1
max = datetime2
else
min = datetime2
max = datetime1
end
max.ago(min.to_i) # min.to_i returns min in seconds since the epoch
end
You figure out which time came first then you return the later of the two times x seconds ago, where x is the earlier time in seconds since the epoch. See http://api.rubyonrails.org/classes/DateTime.html#method-i-3C-3D-3E

Related

from and to ranges in mysql

Currently I have this kind of query
SELECT
part_number,
part_name,
attenuation_low_end,
attenuation_high_end,
optimum_fermentation_temp_f_low,
optimum_fermentation_temp_f_high
FROM
yeast_module
WHERE
category = 3
AND
(
( `attenuation_low_end` > '31' OR `attenuation_low_end` = '31' )
AND
( `attenuation_high_end` < '40' OR `attenuation_high_end` = '40' )
)
Where I'm trying to get the records with the range of low to high end from 31 and maximum of 40
But it returns me something like this
As you can notice it seems doesn't return the data between 31 to 40
Am I doing this right?
UPDATE
I'm expecting no return since, there's no data between 31-40
You're comparing strings, which performs lexicographic comparisons rather than numeric comparisons. You need to convert to numbers. Adding 0 to a numeric string is a simple way to convert it to a number.
WHERE 0+attenuation_low_end >= 31 AND 0+attenuation_high_end <= 40
If you want ranges contained in the 31-40 range:
where attenuation_low_end >= 31 and attenuation_high_end <= 40
If you want ranges that overlap the 31-40 range:
where attenuation_low_end <= 40 and attenuation_high_end >= 31
If your data is of a string datatype, then you need to convert the values to integers so they can be compared as such.
Containment:
where attenuation_low_end + 0 >= 31 and attenuation_high_end + 0 <= 40
Overlap:
where attenuation_low_end + 0 <= 40 and attenuation_high_end + 0 >= 31

Converting Month Number(Date Time or 4 byte integer) to Month Name(String) SSIS

I need to convert month number to month name.
I have date time as the date type - 2009-01-01 00:00:00.000
I also have 4-byte integer data type - 1
how do I convert this 1 to "January" for example?
i think you are in the data flow:
it is really easy to get MOnth Name in a script component from Date:
add a varchar column to your dataflow
Mark your date column for read access
enter the following script
Row.[NewColumnName] = Row.[Your Date Column].ToString("MMMM");
Result:
Here is a good translations for any date part to string formatting:
// create date time 2008-03-09 16:05:07.123
DateTime dt = new DateTime(2008, 3, 9, 16, 5, 7, 123);
String.Format("{0:y yy yyy yyyy}", dt); // "8 08 008 2008" year
String.Format("{0:M MM MMM MMMM}", dt); // "3 03 Mar March" month
String.Format("{0:d dd ddd dddd}", dt); // "9 09 Sun Sunday" day
String.Format("{0:h hh H HH}", dt); // "4 04 16 16" hour 12/24
String.Format("{0:m mm}", dt); // "5 05" minute
String.Format("{0:s ss}", dt); // "7 07" second
String.Format("{0:f ff fff ffff}", dt); // "1 12 123 1230" sec.fraction
String.Format("{0:F FF FFF FFFF}", dt); // "1 12 123 123" without zeroes
String.Format("{0:t tt}", dt); // "P PM" A.M. or P.M.
String.Format("{0:z zz zzz}", dt); // "-6 -06 -06:00" time zone
Furthermore, you asked about quarters. I don't think it is as easy but here is something I stole from another answer.
Build DateTime extensions:
Normal Quarter:
public static int GetQuarter(this DateTime date)
{
return (date.Month + 2)/3;
}
Financial Year Quarter (This case is for quarters that start on April 1):
public static int GetFinancialQuarter(this DateTime date)
{
return (date.AddMonths(-3).Month + 2)/3;
}
Integer division will truncate decimals, giving you an integer result. Place methods into a static class and you will have an extension method to be used as follows:
Row.calendarQuarter = Row.[your Date Column].GetQuarter()
Row.fiscalQuarter = Row.[your Date Column].GetFinancialQuarter()
In SQL Server, one method is:
select datename(month, datefromparts(2000, 1, 1))
The first "1" is the column for the month. The year is arbitrary.
following steps:
create variable with datetime datatype and assigned value.
used MONTH function in ssis to extract month number and assigned to new variable with integer data type: #[User::newdata]= MONTH( #[User::dbdate])
finally used if else condition which manually compare all 12 months
(code available:1)

Checking to see if today is in the scheduled day utilizing a binary mapping table in SQL

I am pulling XML data from a 3rd party application using SQL Server 2008 (which I only have read-only access to the DB) and it stores the day or days of the week a job is supposed to run in one of those XML fields.
SQL uses a recursive day code of Sunday=1, Monday=2, Tuesday=4, Wednesday=8, Thursday=16, Friday=32, Saturday=64.
I am pulling the day from this XML field like the following.
case
when (job.SJDefn.value('(schedules/schedule/name)[1]', 'varchar(30)') ) like '%Week%'
then job.SJDefn.value('(/schedules/schedule/recurring/date/week/day_of_week)[1]', 'int')
else 0
end as JDOW,
I was originally utilizing the this to determine the current date of the week as but the values were obviously not compatible.
DATEPART(dw, getdate()) AS CDOW, -- Sun 1 Mon 2 Tue 3 Wed 4 Thu 5 Fri 6 Sat 7`
So I moved to:
case DATEPART(dw, getdate())
when 1 then 1 -- Sunday (1=1)
when 2 then 2 -- Monday (2=2)
when 3 then 4 -- Tueday (3=4
when 4 then 8 -- Wednesday (4=8)
when 5 then 16 -- Thursday (5=16)
when 6 then 32 -- Friday (6=32)
when 7 then 64 -- Saturday (7=64)
else NULL
end as CDOW,
The challenge is that it is an easy translation when the job just runs one day of a week.. but what about Monday/Wednesday/Friday well that is 42 which is an aggregate of the days Monday (2) + Wednesdays (8) + Friday (32).
I could translate this to text like in this question and do a string compare to a temp table but that seems inefficient.
I know that there is a table that can be built like this code to build a comparison table and I've checked the SQL Server Agent documentation (which this isn't but it is quite similar.
It seems like all possible combinations for Sunday - Saturday are basically a bitmap ranged from 1-127.. such as 42 = 0010 1010 which could be an on/off values for each day (first position always 0, 127 = 0111 111) and with that.
Position 1 = Always 0 ; binary 0000 0000
Position 2 = Sunday 1 ; binary 0000 0001
Position 3 = Monday 2 ; binary 0000 0010
Position 4 = Tueday 4 ; binary 0000 0100
Position 5 = Wednesday 8 ; binary 0000 1000
Position 6 = Thursday 16 ; binary 0001 0000
Position 7 = Friday 32 ; binary 0010 0000
Position 8 = Saturday 64 ; binary 0100 0000
I am thinking about how to potentially use a bitwise & operator but it compares the entire bit for an exact match and not a single position as I understand it so not thinking it will accomplish exactly what I want.
What I want is if the current day is in the schedule I get a true / false result from the comparison. I don’t care about interpreting the values into plain English.. For example if the string was 0011 1110 (Monday - Friday), then if the current day value is the equivalent of 0000 0010 (Monday) I be get true. If it was Sunday (0000 0001) it would be false if the reference was that 0010 1110.
I would really think there is a much simpler way of simply checking if the current day falls into the configuration in a few lines vs. building a temporary table to compare against.
So my question: given the information above, is there a simple function / query that I can execute to compare the two and return a boolean result (0/1 or Y/N) if the the current day matches the schedule?
This will give you a 1/0 result for the current date given a schedule bitmap:
declare #Today as Date = GetDate();
-- Assuming that ##DateFirst is correctly set:
declare #DoW as Int = DatePart( weekday, #Today );
-- Shift a bit to the appropriate position.
declare #Mask as Int = Power( 2, #DoW - 1 );
-- Sample schedule bitmap.
declare #Schedule as Int = 42;
-- Sign is used to convert the result of the bitwise-and to a 0 or 1.
-- Any positive value, indicating the corresponding bit is set, will return 1.
-- If there is no match, the result will be zero.
select #Today as Today, #DoW as Dow, #Mask as Mask, #Schedule as Schedule,
Sign( #Schedule & #Mask ) as IsScheduledToday;
As a professor once said, "you're always off by one in this business." It may need a tweak, but should be close.
It's a little difficult to tell exactly what you're trying to do here. You've explained the problem, but didn't provide any desired output. Since you have read-only access, however, I assume you're only interested in querying the data.
However, if you have an integer like 42, and you want to test bitwise if the bit for Monday is set (that is, 2's place), then you do this:
42 & 2 = 2
If you want to display days of the week you could do something like:
SELECT
CASE WHEN JDOW & 1 = 1 THEN 'U' ELSE '' END
+ CASE WHEN JDOW & 2 = 2 THEN 'M' ELSE '' END
+ CASE WHEN JDOW & 4 = 4 THEN 'T' ELSE '' END
+ CASE WHEN JDOW & 8 = 8 THEN 'W' ELSE '' END
+ CASE WHEN JDOW & 16 = 16 THEN 'R' ELSE '' END
+ CASE WHEN JDOW & 32 = 32 THEN 'F' ELSE '' END
+ CASE WHEN JDOW & 64 = 64 THEN 'S' ELSE '' END AS scheduled_days
FROM (VALUES (42),(84),(96), (4)) UnnamedTable (JDOW)
If you want you could create another table:
CREATE TABLE BitwiseWeekDay (
code tinyint primary key not null,
day_name nvarchar(10) not null,
day_short_name nvarchar(4) not null,
day_code nvarchar(1) not null
)
INSERT INTO BitwiseWeekDay VALUES
(1,'Sunday','Sun','U'),
(2,'Monday','Mon','M'),
(4,'Tuesday','Tue','T'),
(8,'Wednesday','Wed','W'),
(16,'Thurday','Thur','R'),
(32,'Friday','Fri','F'),
(64,'Saturday','Sat','U')
SELECT u.JDOW,
b.code,
b.day_name
FROM (VALUES (42),(84),(96), (4)) u (JDOW)
INNER JOIN BitwiseWeekDay b
ON u.JDOW & b.code = b.code
ORDER BY u.JDOW, b.code
But, I don't really know what you're looking for.

MySQL Convert From Seconds To Another Custom Format

I have this javascript code that works fine:
function timeup(s) {
var d, h, m, s;
m = Math.floor(s / 60);
s = s % 60;
h = Math.floor(m / 60);
m = m % 60;
d = Math.floor(h / 24);
h = h % 24;
m = m > 9 ? m : "0"+m;
h = h > 9 ? h : "0"+h;
s = s > 9 ? s : "0"+s;
if (d > 0) {
d = d+" days ";
} else {
d = "";
}
return d+h+":"+m+":"+s;
}
SO i need same function but in MySQL(because i do SQL query and don't want to use javascript conversion on client side)
So i need to convert in MySQL seconds to get this same output:
timeup(600000) => 6 days 22:40:00
timeup(60000) => 16:40:00
timeup(6000) => 01:40:00
timeup(600) => 00:10:00
timeup(60) => 00:01:00
timeup(60) => 00:01:00
timeup(6) => 00:00:06
So if seconds below day show HH:MM:SS if seconds greater that day show X days HH:MM:SS
I im trying using CONCAT & TIMESTAMPDIFF but i think maybe it should go if then to compare day below 24h or grater to show custom string X days...any help welcome.
I tested this and it seems to do the job:
DROP FUNCTION IF EXISTS GET_HOUR_MINUTES;
DELIMITER $$
CREATE FUNCTION GET_HOUR_MINUTES(seconds INT)
RETURNS VARCHAR(16)
BEGIN
RETURN CONCAT(LPAD(FLOOR(HOUR(SEC_TO_TIME(seconds)) / 24), 2, 0), ' days ',TIME_FORMAT(SEC_TO_TIME(seconds % (24 * 3600)), '%H:%i:%s'));
END;
$$
DELIMITER ;
Test it like this:
SELECT GET_HOUR_MINUTES(600001);
That returns
'06 days 22:40:01'
It seems to want, at least in MySQL Workbench, to have the database you are using selected before you run it. It saves the function within the database, that is, you can see it in the column on the left with Tables, Views, Stored Procedures and Functions.
I now have another problem with this above function that works only on seconds..but i forget to ask in first question that i have in database stored number:
uptime => 1507977507423
And i need to get seconds and show above format from NOW() time
So for example if i have uptime in database so formula will be: NOW() - uptime, i try using this but i get strange output like 34 days 838:59:59 and that is not correct:
SELECT
CONCAT(LPAD(FLOOR(HOUR(SEC_TO_TIME(UNIX_TIMESTAMP(NOW())-SUBSTRING(uptime, 1, length(uptime) - 2))) / 24), 2, 0), ' days ',TIME_FORMAT(SEC_TO_TIME(UNIX_TIMESTAMP(NOW())-SUBSTRING(uptime, 1, length(uptime) - 2) % (24 * 3600)), '%H:%i:%s')) AS nice_date
FROM streams
WHERE id=1;
I get this:
+-------------------+
| nice_date |
+-------------------+
| 34 days 838:59:59 |
+-------------------+

Use R or mysql to calculate time period returns?

I'm trying to calculate various time period returns (monthly, quarterly, yearly etc.) for each unique member (identified by Code in the example below) of a data set. The data set will contain monthly pricing information for a 20 year period for approximately 500 stocks. An example of the data is below:
Date Code Price Dividend
1 2005-01-31 xyz 1000.00 20.0
2 2005-01-31 abc 1.00 0.1
3 2005-02-28 xyz 1030.00 20.0
4 2005-02-28 abc 1.01 0.1
5 2005-03-31 xyz 1071.20 20.0
6 2005-03-31 abc 1.03 0.1
7 2005-04-30 xyz 1124.76 20.0
I am fairly new to R, but thought that there would be a more efficient solution than looping through each Code and then each Date as shown here:
uniqueDates <- unique(data$Date)
uniqueCodes <- unique(data$Code
for (date in uniqueDates) {
for (code in uniqueCodes) {
nextDate <- seq.Date(from=stock_data$Date[i], by="3 months",length.out=2)[2]
curPrice <- data$Price[data$Date == date]
futPrice <- data$Price[data$Date == nextDate]
data$ret[(data$Date == date) & (data$Code == code)] <- (futPrice/curPrice)-1
}
}
This method in itself has an issue in that seq.Date does not always return the final day in the month.
Unfortunately the data is not uniform (the number of companies/codes varies over time) so using a simple row offset won't work. The calculation must match the Code and Date with the desired date offset.
I had initially tried selecting the future dates by using the seq.Date function
data$ret = (data[(data$Date == (seq.Date(from = data$Date, by="3 month", length.out=2)[2])), "Price"] / data$Price) - 1
But this generated an error as seq.Date requires a single entry.
> Error in seq.Date(from = stock_data$Date, by = "3 month", length.out =
> 2) : 'from' must be of length 1
I thought that R would be well suited to this type of calculation but perhaps not. Since all the data is in a mysql database I am now thinking that it might be faster/easier to do this calc directly in the database.
Any suggestions would be greatly appreciated.
Load data:
tc='
Date Code Price Dividend
2005-01-31 xyz 1000.00 20.0
2005-01-31 abc 1.00 0.1
2005-02-28 xyz 1030.00 20.0
2005-02-28 abc 1.01 0.1
2005-03-31 xyz 1071.20 20.0
2005-03-31 abc 1.03 0.1
2005-04-30 xyz 1124.76 20.0'
df = read.table(text=tc,header=T)
df$Date=as.Date(df$Date,"%Y-%m-%d")
First I would organize the data by date:
library(plyr)
pp1=reshape(df,timevar='Code',idvar='Date',direction='wide')
Then you would like to obtain monthly, quarterly, yearly, etc returns.
For that there are several options, one could be:
Make the data zoo or xts class. i.e
library(xts)
pp1[2:ncol(pp1)] = as.xts(pp1[2:ncol(pp1)],order.by=pp1$Date)
#let's create a function for calculating returns.
rets<-function(x,lag=1){
return(diff(log(x),lag))
}
Since this database is monthly, the lags for the returns will be:
monthly=1, quaterly=3, yearly =12. for instance let's calculate monthly return
for xyz.
lagged=1 #for monthly
This calculates Monthly returns for xyz
pp1$returns_xyz= c(NA,rets(pp1$Price.xyz,lagged))
To get all the returns:
#create matrix of returns
pricelist= ls(pp1)[grep('Price',ls(pp1))]
returnsmatrix = data.frame(matrix(rep(0,(nrow(pp1)-1)*length(pricelist)),ncol=length(pricelist)))
j=1
for(i in pricelist){
n = which(names(pp1) == i)
returnsmatrix[,j] = rets(pp1[,n],1)
j=j+1
}
#column names
codename= gsub("Price.", "", pricelist, fixed = TRUE)
names(returnsmatrix)=paste('ret',codename,sep='.')
returnsmatrix
You can do this very easily with the quantmod and xts packages. Using the data in AndresT's answer:
library(quantmod) # loads xts too
pp1 <- reshape(df,timevar='Code',idvar='Date',direction='wide')
# create an xts object
x <- xts(pp1[,-1], pp1[,1])
# only get the "Price.*" columns
p <- getPrice(x)
# run the periodReturn function on each column
r <- apply(p, 2, periodReturn, period="monthly", type="log")
# merge prior result into a multi-column object
r <- do.call(merge, r)
# rename columns
names(r) <- paste("monthly.return",
sapply(strsplit(names(p),"\\."), "[", 2), sep=".")
Which leaves you with an r xts object containing:
monthly.return.xyz monthly.return.abc
2005-01-31 0.00000000 0.000000000
2005-02-28 0.02955880 0.009950331
2005-03-31 0.03922071 0.019608471
2005-04-30 0.04879016 NA