It seems like the Play Framework used(?) to have a since() function to get relative time (like "4 minutes ago") in views for Play 1.x. This is mentioned as a Date Extension here
However in Play 2.1 this doesn't appear to work anymore. I get value since is not a member of java.util.Date ... Additionally I can't find any other references to since() (in the context of Play 2.1) online.
Is there a proper/default way of handling this common case? I feel like I must be missing something important since this seems to no longer be supported?
Thanks!
The since() method is unavailable since beginning of the 2.0 branch.
Not a direct answer, but if it's possible I'd suggest to use JavaScript plugin for this task for an example: timeago jQuery plugin reasons:
It doesn't require calculating it in the controller
You can cache your site (for an example in the memory) for long time, and since time will be still displayed correctly as it's updated on the client-side.
It auto updates even without page refresh (like here, on the Stack Overflow)
#Jack suggested a pretty good answer.
Here is a version of his code that might be useful because it'll enable some composition if needed (the check function is not composing but could be easily changed to compose and show a more detailed since value)
package object pimps {
import java.util.Date
import org.joda.time.DateTime;
import org.joda.time.Period;
def step(f:Period => Int)(fi:String):Period => Option[String] = {
def g(i:Int = 1) = i + " " + fi + (if (i==1) "" else "s") + " ago"
(p:Period) => {
f(p) match {
case 0 => None
case 1 => Some(g())
case x => Some(g(x))
}
}
}
val yearsStep = step(_.getYears)("year")
val monthsStep = step(_.getMonths)("month")
val daysStep = step(_.getDays)("day")
val hoursStep = step(_.getHours)("hour")
val minutesStep = step(_.getMinutes)("minute")
val secondsStep = step(_.getSeconds)("second")
val steps = Seq(yearsStep, monthsStep, daysStep, hoursStep, minutesStep, secondsStep)
val check =
(p:Period) =>
steps.collectFirst {
case f if f(p).isDefined => f(p).get
}
implicit class PimpedDate(col: Date) {
def since() = {
val period: Period = new Period(new DateTime(col), DateTime.now);
check(period)
}
}
}
As you can see, for now we stop at the first matching level, and also we repeat the getter (getYears if matching will be called twice).
Nevertheless, another thing to note is the usage of implicit class which has been introduced in Scala 2.10 to ease the pimping
As far as I can tell this isn't possible to do any more (by default in Play2.1). Please correct me if I am wrong. Here's how I recreated it. As mentioned here I "pimped" the "Date" class:
// File app/views/pimps.scala
package views
package object pimps {
import java.util.Date
import org.joda.time.DateTime;
import org.joda.time.Period;
class PimpedDate(col: Date) {
def since() = {
def addS(b: Int) = if (b == 1) "" else "s"
val now: DateTime = new DateTime();
val period: Period = new Period(new DateTime(col), now);
var r: String = "";
if (period.getYears() > 0) {
r = period.getYears() + " year" + addS(period.getYears()) + " ago";
} else if (period.getWeeks() > 0) {
r = period.getWeeks() + " week" + addS(period.getWeeks()) + " ago";
} else if (period.getMonths() > 0) {
r = period.getMonths() + " month" + addS(period.getMonths()) + " ago";
} else if (period.getDays() > 0) {
r = period.getDays() + " day" + addS(period.getDays()) + " ago";
} else if (period.getHours() > 0) {
r = period.getHours() + " hour" + addS(period.getHours()) + " ago";
} else if (period.getMinutes() > 0) {
r = period.getMinutes() + " minute" + addS(period.getMinutes()) + " ago";
} else {
r = period.getSeconds() + " second" + addS(period.getSeconds()) + " ago";
}
r
}
}
implicit def pimpDate(col: Date) = new PimpedDate(col)
}
Then in my view I can just import the above:
#import views.pimps._
and then use since() just as you could in Play1
<td>#record.created_on.since()</td>
Please comment/answer if there's a better way to do this or write the scala code...
Related
I'm USING GATLING AND trying to use in java's library "Base64" in scala for sending encode uder:password in header ("authorization") request, with dynamic values:
I'm trying to do as follow :
val register = {
exec(request.asJSON
.check(status.is(200))
.check(jsonPath("$..user").saveAs("user"))
.check(jsonPath("$..password").saveAs("password"))
).pause(1)
}
val myvalue: HttpRequestBuilder = Utils.createPostFormParamsRequest(
"myvalue",
login,
Map("value"-> ("Basic " + Base64.getEncoder.encodeToString((("${user}").getBytes() + ":" + ("${password}").getBytes()).getBytes("utf-8")))),
Map())
I'd tried also Base64.getEncoder.encodeToString(("${uesr}" + ":" + "${password}").getBytes("utf-8"))))
But it seems like the Base64 take the String "${user}" and not the actual value, so the encryption does not work properly.
I'd tried to :
val helper = {
exec { session =>
val user : String= (session("user").as[String])
val password : String= (session("password").as[String])
val temp = "Basic " + Base64.getEncoder.encodeToString((user + ":" + password).getBytes("utf-8"))
val temp2: HttpRequestBuilder = Utils.createPostFormParamsRequest(
"bla",
login,
Map("value"-> temp),
Map())
val assert = {
exec(helper.asJSON
.check(status.is(200))
.check(header("answer").saveAs("answer"))
).pause(1)
}
session
}
And here the encryption works properly, but the "exec" do not.
There is a way to save the values in run time without part of the exec?
I don't know Gatling that well, but I think this should work. It's not the prettiest but without seeing the full code and how it's used it's a bit difficult to come up with something that looks good:
var token: String = null
val registerAssert = exec(...)
def finalToken = {
Utils.createPostFormParamsRequest(
"Final token",
Constants.LOGIN,
Map("Authorization"-> token),
Map())
}
def saveToken(s: Session) = {
token = "Basic " + Base64.getEncoder.encodeToString((s("uuid").as[String].getBytes() + ":" + s("secret").as[String].getBytes()).getBytes("utf-8")
s
}
// now you're actually executing the above
scenario(...)
.exec(registerAssert)
.exec(saveToken(_))
.exec(finalToken) // I'm assuming finalToken is executable
The intention of this is to first save the token value in a class variable, and then only construct the finalToken request (which uses that token) afterwards. Hence the def, and when it's called the token value will have been set.
I would like to access the field called Date and time from Event Viewer through Java. I managed to get the EventID :
EVENTLOGRECORD record = new EVENTLOGRECORD(pevlr);
if (record.EventID.shortValue() == 4624) {
System.out.println("Successful log in: " + " Event ID: " + record.EventID.shortValue());
}
if (record.EventID.shortValue() == 4634) {
System.out.println("Successful log out: " + " Event ID: " + record.EventID.shortValue());
}
And now the next step would be to get the Date and time
If anyone could help i would really appreciate it !
Meanwhile I figured out how to get the Date and time field. Just used :
long timestamp = record.TimeGenerated.longValue() * 1000;
Date d = new Date(timestamp);
when calling
twitter.list().getUserListMemberships(userId, 1000,1,false);
I get this error:
java.lang.NoSuchMethodError: twitter4j.api.ListsResources.getUserListMemberships(JIJ)Ltwitter4j/PagableResponseList;
I read the javadoc for this method (see here), and I don't see what I am doing wrong? And I did verify that my dependencies are OK. Any clue?
I just use Twitter4j 4.0.2 and that method doesn't exist
But on Twitter4j 4.0.4 does exist
So, Are you sure that you are using 4.0.4?
Keep in mind too that you are using cursor 1 on the first call but you have to use -1. I just run this code and works
User user = twitter.showUser("lt_deportes");
long cursor = -1;
PagableResponseList<UserList> lists;
do {
lists = twitter.list().getUserListMemberships(user.getId(),1000,cursor,false);
for (UserList list : lists) {
System.out.println("id:" + list.getId() + ", name:" + list.getName() + ", description:"
+ list.getDescription() + ", slug:" + list.getSlug() + "");
}
} while ((cursor = lists.getNextCursor()) != 0);
I have two datepickers for search parameters but i cant have the search more then a week(to much of a load on the server) so i want to check if the first date is before the second one, and if the first date and second date are less then 7 days apart. if all is correct then return a true boolean if not false.
public Calendar max = Calendar.getInstance();
public boolean checkweek(Calendar cStart, Calendar cEnd) {
Toast.makeText(this,
cStart.DAY_OF_MONTH + " - " + cStart.MONTH + " - " + cStart.YEAR, Toast.LENGTH_LONG).show();
if (cEnd.after(cStart) || ((cEnd.DAY_OF_MONTH == cStart.DAY_OF_MONTH) && (cEnd.MONTH == cStart.MONTH))) {
max.set(Calendar.YEAR, cStart.YEAR);
max.set(Calendar.MONTH, cStart.MONTH);
max.set(Calendar.DAY_OF_MONTH, cStart.DAY_OF_MONTH);
max.add(Calendar.DAY_OF_MONTH, 7);
Toast.makeText(this,
max.DAY_OF_MONTH + " - " + max.MONTH + " - " + max.YEAR,
Toast.LENGTH_LONG).show();
if (cEnd.before(max)) {
return true;
}
else{
return false;
}
}
else{
return false;}
}
But it throws a null exception. im declaring the cStart and cEnd so i have no idea what it is...
Why not just use math for this?
cEnd.getTimeInMillis() - cStart.getTimeInMillis() > (7L * 24L * 60L * 60L * 1000L)
Or, thanks to #Sam, you can make this simpler using DateUtils.WEEK_IN_MILLIS:
cEnd.getTimeInMillis() - cStart.getTimeInMillis() > DateUtils.WEEK_IN_MILLIS
How it works: Calendar.getTime().getTime() will return a long of the milliseconds value. Just subtract them (to get the difference), then check if it's greater than 604800000L (milliseconds in a week, per above formula).
This should provide no NullPointerException if run when cStart and cEnd are non-null.
Eric's answer works and is probably the best solution to your problem.
To fix your own code; however, you have to use cEnd.get( Calendar.DAY_OF_MONTH ) instead of cEnd.DAY_OF_MONTH and so on for the rest of them.
I am designing an emergency response page, which needs to display information across 3 different monitors. The first monitor will gather information about the caller, and then contain 2 links. The first link needs to display a different web page on the 2nd monitor, and the 2nd link needs to display a different web page on the 3rd monitor.
Is this possible?
Thanks for any help
The first link needs to display a different web page on the 2nd monitor, and the 2nd link needs to display a different web page on the 3rd monitor.
While, depending on your operating system, it is possible to control where a window appears, there are much fewer options for doing this using javascript / serverside code over HTTP / browsers.
The only sensible way to achieve this is by configuring the displays to be tiles of a larger display rather than independent screens (for *nix/BSD/Linux, check out xinerama).
The code below saves the size of a window - and would only need some simple changes to support x/y offset and multiple windows - I leave it to you as to how you differentiate between the windows.
A simpler approach would be to just have one huge window with frames whose borders align with the monitors.
if (document.getElementById && !document.all) { // NOT for MSIE
stickySizeOverloadOnload(stickySizeSetWindowSize);
stickySizeOverloadOnresize(stickySizeSaveWindowSize);
}
function stickySizeSaveWindowSize(event)
{
var expiry = new Date();
var path = document.location.pathname;
expiry.setDate(expiry.getDate()+500);
stickySizeSetCookie('windowSize', window.outerWidth + ',' + window.outerHeight, expiry, path);
}
function stickySizeSetWindowSize()
{
var saved=stickySizeGetCookie('windowSize');
var parts=new Array();
if (saved.length) {
parts = saved.split(',');
if ((parts[0]>100) && (parts[1]>100)) {
window.outerWidth=parts[0];
window.outerHeight=parts[1];
} else {
alert("invalid size - '" + saved + "'");
stickySizeDeleteCookie('windowSize');
}
}
}
function stickySizeOverloadOnload(func)
{
var oldhandler=window.onload;
if (typeof window.onload != "function") {
window.onload=func;
} else {
window.onload=function(event) {
oldhandler(event);
func(event);
}
}
}
function stickySizeOverloadOnresize(func)
{
var oldhandler=window.onresize;
if (typeof window.onresize != "function") {
window.onresize=func;
} else {
window.onresize=function(event) {
oldhandler(event);
func(event);
}
}
}
function stickySizeSetCookie(name, value, expires, path, domain, secure) {
var curCookie = name + "=" + escape(value) +
((expires) ? "; expires=" + expires.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "");
document.cookie = curCookie;
}
function stickySizeGetCookie(name) {
var dc = document.cookie;
var prefix = name + "=";
var begin = dc.indexOf("; " + prefix);
if (begin == -1) {
begin = dc.indexOf(prefix);
if (begin != 0) return null;
} else
begin += 2;
var end = document.cookie.indexOf(";", begin);
if (end == -1)
end = dc.length;
return unescape(dc.substring(begin + prefix.length, end));
}
function stickySizeDeleteCookie(name, path, domain) {
if (stickySizeGetCookie(name)) {
document.cookie = name + "=" +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
"; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
}
You can open the links in a different window with the attribute target="windowName".
You have to set up the three windows manually, so assign them manually to the three screens. When you open a link again in a window it is still on the same screen.
Have a look at Java: Getting resolutions of one/all available monitors (instead of the whole desktop)?
(The answer discuss the GraphicsEnvironment.getLocalGraphicsEnvironment() call)
If you really want the windows to be locked to a specific monitor, you will need to implement this client side. Here is a link describing how to detect which monitor a window is on in Java, so you can move it to the proper monitor and maximize the window if you desire. Obviously you can implement the rest of the system server side and just display pages inside the windows you have created.