Adding two hours and minutes in dataweave 2.0 - java

I need to sum the below hours and minutes.
[{"hours": 20.50},{"hours":30.55}]
expecting result should be: [{"hours" : 51.45}]
How do you think I can add the hours in dataweave 2.0 if not help me in java.

I'm not sure if we can take advantage of the Time Types that include DW to solve this, so I wrote a solution that uses a custom type HoursMinutes that let the hours to be more than 24, parse a Number to HoursMinutes, add them, and finally transform it again to Number.
Maybe I over complicate it... hahah
%dw 2.0
output application/json
type HoursMinutes = {hour:Number, minute: Number}
fun toHours(n: Number): HoursMinutes = do {
var split = n as String splitBy "."
var fromMin = floor(split[1] as Number / 60)
---
{hour:floor(n) + fromMin, minute:split[1] as Number mod 60}
}
fun add(hour1:HoursMinutes, hour2: HoursMinutes): HoursMinutes = do {
var fromMin = floor((hour1.minute + hour2.minute) / 60)
---
{hour: hour1.hour + hour2.hour + fromMin, minute: (hour1.minute + hour2.minute) mod 60}
}
fun toNumber(h: HoursMinutes) = (h.hour as String ++"."++ h.minute as String) as Number
---
[
{
"hours": toNumber(payload reduce ((item, accumulator:HoursMinutes = {hour:0, minute:0}) -> accumulator add toHours(item.hours)))
}
]

Related

Looking for a Play Framework pagination example

I'm looking for a Play Framework pagination example. Please help me with a good reference link.
I searched for it and don't have java code.
I'll provide a Scala solution and you can adjust your code.
You could create a utility class called Paginator:
package util
case class Paginator[A](items: Seq[A], page: Int, offset: Long, total: Long) {
lazy private val pageSize: Int = 20 // you can adjust to your preference
lazy val prevPage: Option[Int] = Option(page - 1).filter(_ >= 0)
lazy val nextPage: Option[Int] = Option(page + 1).filter(_ => (offset + items.size) < total)
lazy val numberOfPages: Float = if (total % pageSize > 0) { total / pageSize + 1 }
else { total / pageSize }
}
In your controller you will do something like:
def list(currentPage: Int) = Action.async { implicit request =>
val offset: Int = currentPage * resultsPerPage
// Put your logic here to get the `listOfItems` you want to display
// and the number of `totalItems`
// and then return Ok and call your view
Ok(views.html.list(Paginator(listOfItems, currentPage, offset, totalItems)))
}
and finally in your view you will have something like:
#import util.Paginator
#(paginatedList: Paginator[Item])(implicit msg: play.api.i18n.MessagesProvider)
#main(msg.messages("label.list_of_items")) {
<h1>#msg.messages("label.paginated_list")</h1>
#* populate your list here *#
#* and this is your paginator *#
<div class="pagination">
#paginatedList.prevPage.map { page =>
<a href="#link(page)">#msg.messages("label.previous")<a>
}.get
#for(pageNumber <- 1 to paginatedList.numberOfPages.toInt) {
#pageNumber
}
#paginatedList.nextPage.map { page =>
#msg.messages("label.next")
}.get
</div>
}
I got the original idea from this project and I've expanded on it. You can also improve the paginator by using getOrElse to provide alternative/disabled links when being on the first/last page, or to disable the current page number etc.
I hope this helps.

Convert the format of a date in Java/Typescript for searchpurposes

I search for a while now, but I didn't found what I need to solve my problem.
First of,I have a "add reminder page" in my app to add reminder with some inputs and the date / time:
<ion-row>
<ion-col>
<ion-label class="ion-label-links" >{{"Datum"|translate}}</ion-label>
</ion-col>
<ion-col text-right>
<ion-label class="ion-label-reminder-rechts">{{"Uhrzeit"|translate}}</ion-label>
</ion-col>
</ion-row>
<ion-row class="schnurr">
<ion-col>
<ion-datetime class="ion-input-reminder" displayFormat="DD.MM.YYYY" [(ngModel)]="reminder.myDate" ></ion-datetime>
</ion-col>
<ion-col>
<ion-datetime text-right class="ion-input-reminder-r" displayFormat="HH:mm" minuteValues="0,5,10,15,20,25,30,35,40,45,50,55" [(ngModel)]="reminder.myTime" ></ion-datetime>
</ion-col>
</ion-row>
And I set a standard date/time with this function:
formatLocalDate() {
var now = new Date(),
tzo = -now.getTimezoneOffset(),
dif = tzo >= 0 ? '+' : '-',
pad = function(num) {
var norm = Math.abs(Math.floor(num));
return (norm < 10 ? '0' : '') + norm;
};
return now.getFullYear()
+ '-' + pad(now.getMonth()+1)
+ '-' + pad(now.getDate())
+ 'T' + pad(now.getHours())
+ ':' + pad(now.getMinutes())
+ ':' + pad(now.getSeconds())
+ dif + pad(tzo / 60)
+ ':' + pad(tzo % 60);
}
Okay, everything is fine. I Save the record in my couchDb and it looks like this:
2017-07-05T09:18:24+02:00
Now the problem with this kind of format is that I implemented a search field but the usual format here is "dd.mm.yyyy" and not the ISO format, so I formated the output in my app like this:
<br><font size="1">{{item.doc.myDate | date:'dd.MM.yyyy, HH:mm'}} Uhr</font>
but if I search for that item, it doesn't work, because the variable is still in the old format.
My search is looking like this:
.....
<ion-item *ngIf="!searchvariable || item.doc.xName.toLowerCase().includes(this.searchvariable)
|| item.doc.myDate.toDateString().includes(this.searchvariable)" class="ion-item1" tappable (click)="openReminder(reminder.doc)" style="background-color: oldlace">
{{item.doc.myDate.toDateString()}}
......
The search is working for everything but the date. (because of the formatproblems)
Is there a possibility to do something like "reminder.myDate.format(xxx)" or something like this?
I mean, it's possible to alter the output, is there a similar way for my search?!
Btw. I have to format the date with this function, otherwise I get errors because the datepicker needs this format.
Thank you!

Parsing JSON objects into a java.util.List using Scala

I'm trying to take the JSON output of an analysis tool, and turn it into a Java list.
I'm doing this with Scala, and while it doesn't sound that hard, I've run into trouble.
So I was hoping the following code would do it:
def returnWarnings(json: JSONObject): java.util.List[String] ={
var bugs = new ArrayBuffer[String]
for (warning <- json.getJSONArray("warnings").){ //might need to add .asScala
bugs += (warning.getString("warning_type") + ": " + warning.getString("message"))
}
val rval: java.util.List[String] = bugs.asJava
rval
}
This block produces two errors when I try to compile it:
Error:(18, 42) value foreach is not a member of org.json.JSONArray
for (warning <- json.getJSONArray("warnings")){ //might need to add .asScala
^
and
Error:(21, 49) value asJava is not a member of scala.collection.mutable.ArrayBuffer[String]
val rval: java.util.List[String] = bugs.asJava
^
I don't know what's wrong with my for loop.
EDIT: with a bit more reading, I figured out what was up with the loop. see https://stackoverflow.com/a/6376083/5843840
The second error is especially baffling, because as far as I can tell it should work. It is really similar to the code from this documentation
scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava
jul: java.util.List[Int] = [1, 2, 3]
You should try the following:
import scala.collection.JavaConverters._
def returnWarnings(input: JSONObject): java.util.List[String] = {
val warningsArray = input.getJSONArray("warnings")
val output = (0 until warningsArray.length).map { i =>
val warning = warningsArray.getJSONObject(i)
warning.getString("warning_type") + ": " + warning.getString("message")
}
output.asJava
}
That final conversion could be done implicitly (without invoking .asJava), by importing scala.collection.JavaConversions._

youtube.subscriptions.list (api v3) - nextPageToken isn't available

I'm trying to get all channels from my subscriptions. But the "nextPageToken" isn't available.
The response should containing "nextPageToken":
(from developers.google.com - YouTube (v3) - Subscriptions: list)
{
"kind": "youtube#subscriptionListResponse",
"etag": etag,
"nextPageToken": string,
"prevPageToken": string,
"pageInfo": {
"totalResults": integer,
"resultsPerPage": integer
},
"items": [
subscription Resource
]
}
This is my request:
GET https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&maxResults=10&mine=true&key={YOUR_API_KEY}
APIs Explorer - YouTube (v3) - Subscriptions.list:
https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.subscriptions.list?part=snippet&maxResults=10&mine=true
My response:
{
"kind": "youtube#subscriptionListResponse",
"etag": "\"XXXXX/XXXXX\"",
"pageInfo": {
"totalResults": 115,
"resultsPerPage": 10
},
"items": [
...
Can you tell me why the nextPageToken is missing, please?
I have now a workaround for this.
Please tell me if that helps.
The tokens seems to be the same for each page of other API Youtube V3 API calls, so I can use it to fetch all pages of subscriptions I need.
tokens = ['CDIQAA','CGQQAA','CJYBEAA','CMgBEAA','CPoBEAA','CKwCEAA','CN4CEAA','CJADEAA','CMIDEAA','CPQDEAA','CKYEEAA', ...]
You can use ANOTHER Youtube API to get more page tokens if you need more. Just fetch 1 element a time and log the tokens to use in this API.
I just need to known when to stop... so I checked when API calls returned no channels!
#retry(stop_max_attempt_number=7)
def get_subscription_page(self, channel_id, pageToken):
print 'Retrieving subscription page using Youtube API (token: %s)' % pageToken
res = self.youtube_data_api.subscriptions().list(part="id,snippet,contentDetails",channelId=channel_id, maxResults=50, pageToken=pageToken).execute()
return res
def get_subscriptions(self, channel_id):
self.authorize(channel_id)
subs = []
# Tokens to deal with api bug...
# https://code.google.com/p/gdata-issues/issues/detail?id=7163
tokens = ['CDIQAA','CGQQAA','CJYBEAA','CMgBEAA','CPoBEAA','CKwCEAA','CN4CEAA','CJADEAA','CMIDEAA','CPQDEAA','CKYEEAA']
iPage = 0
pageToken = ''
while True:
res = self.get_subscription_page(channel_id, pageToken)
channelIds = []
for channel in res['items']: channelIds.append(channel.get('snippet').get('resourceId').get('channelId'))
pageToken = res.get('nextPageToken')
# If no next page token is returned... it might be caused by a bug.
# This workaroud will only have effect when the bug still lives.
if not pageToken:
if not channelIds:
# Workaroud for this: https://code.google.com/p/gdata-issues/issues/detail?id=7163
print ' (Workaround due to API bug) No channels returned in this API call! Finished!'
break
else:
pageToken = tokens[iPage]
# get channel info for each channel ID
channelsInfo = self.get_channel_info(channelIds)
subs += channelsInfo
print ' Itens already retrieved: %d ' % len(subs)
iPage += 1
if args.debug: break
if pageToken: continue
print 'No more pages to retrieve!'
break
return subs
Here is a JS snippet I came up with to generate pageTokens up to at least 1024, I cannot guarantee that it will produce anything valid beyond that as i could not find any service which will get me tokens for offsets > 450 to validate my guesses and assumptions.
var d0 = "AEIMQUYcgkosw048";
var d1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var d2 = d1;
var d1c = 0;
var d2c = 0;
var overflowSuffix = "Q";
var direction = "AA";
var d2OverflowCounter = 0;
var pageSize = 50;
for (i = 0; i < 1024; i++) {
if (i % pageSize == 0) console.log("C" + d1.charAt((d1c / d0.length) % d1.length) + d0.charAt(i % d0.length) + overflowSuffix + direction, ":", i);
if (++d1c % (1 << 8) == 0) d1c = 1 << 7;
if (++d2c % (1 << 7) == 0) overflowSuffix = d2.charAt(++d2OverflowCounter) + "E";
}
(check developer tools / console to see generated codes)
I have a script that runs each hour based on this Youtube API V3 and it stopped to work 4 hours ago. The nextPageToken is not available anymore. Before, it was available exactly like in the first code you posted.

Conversion from "datetime-local" to java.sql.Timestamp

I have a form with input of type "datetime-local" on a jsp page, the data is passed to a servlet:
String resetTimeString = request.getParameter(RequestParameterName.RESET_TIME);
How to convert the input to java.sql.Timestamp?
EDIT:
Well, I found something new!
You can use Timestamp.valueOf() to format a time-string with the value of yyyy-[m]m-[d]d hh:mm:ss[.f...]
So it can also handle micro/nano seconds. The only thing you need to do is replace the T with a space.
This works:
String datetimeLocal = "1985-04-12T23:20:50.52";
System.out.println(Timestamp.valueOf(datetimeLocal.replace("T"," ")));
The output:
1985-04-12 23:20:50.52
According to this site your resetTimeString looks like this: '1985-04-12T23:20:50.52' (a string)
I couldn't find a method to convert this to a timestamp directly, but you could just split it up manually:
String[] dateTime = datetimeLocal.split("T");
String[] date = dateTime[0].split("-");
String[] time = dateTime[1].split(":");
This will print:
System.out.println("DateTime: " + Arrays.toString(dateTime));
System.out.println("Date: " + Arrays.toString(date));
System.out.println("Time: " + Arrays.toString(time));
>>> DateTime: [1985-04-12, 23:20:50]
>>> Date: [1985, 04, 12]
>>> Time: [23, 20, 50]
After that you could just create a new Timestamp: (This is deprecated!)
Timestamp stamp = new Timestamp(Integer.valueOf(date[0]).intValue() - 1900,
Integer.valueOf(date[1]).intValue(),
Integer.valueOf(date[2]).intValue(),
Integer.valueOf(time[0]).intValue(),
Integer.valueOf(time[1]).intValue(),
Integer.valueOf(time[2].split("\\.")[0]).intValue(),
Integer.valueOf(time[2].split("\\.")[1]).intValue());
Note that, if you use this you need to subtract '1900' from the year and split dots with \\.
Also, you'd need to handle nanoseconds (In my example I'm using the value 50.52 as seconds, but the string returned from your server might not contain the nanoseconds)
You could also calculate a long from the date and use new Timestamp(<long>)
I hope this helps :)
Cyphrags' answer won't work if seconds are set to "00", because Chrome won't send the seconds part resulting in a java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff] when calling Timestamp.valueOf().
Therefore a more complete answer could be:
String datetimeLocal = "1985-04-12T23:20";
// make sure the seconds are set before parsing
if (StringUtils.countMatches(datetimelocal, ":") == 1) {
datetimelocal += ":00";
}
Timestamp value = Timestamp.valueOf(datetimeLocal.replace("T", " "));

Categories