DATA(lv_js_timestamp) = "/Date(1615161600000)/".
"Extract /Date(1615161600000)/ to 1615161600000
FIND REGEX '([0-9]+)' IN lv_js_timestamp IGNORING CASE SUBMATCHES DATA(js_timestamp).
cl_pco_utility=>convert_java_timestamp_to_abap( EXPORTING iv_timestamp = js_timestamp
IMPORTING ev_date = DATA(lv_date)
ev_time = DATA(lv_time) ).
"2021-03-08T00:00:00
CONVERT DATE lv_date TIME lv_time INTO TIME STAMP DATA(timestamp) TIME ZONE 'UTC'.
rv_datetime = |{ timestamp TIMESTAMP = ISO }|.
[Deutsch] Aliquotierung
https://de.wikipedia.org/wiki/Aliquotierung
Aliquotierung oder das zugehörige Verb aliquotieren bedeuten im allgemeinen Sprachsinn „den aliquoten Teil einer Größe bestimmen“.
https://de.wiktionary.org/wiki/Aliquotierung
[1] Betriebswirtschaft, Personalwirtschaft: die anteilsmäßige, periodenbezogene Berechnung und Ermittlung von Ansprüchen (Urlaub, Sonderzahlungen, Entgelt etc.) für einen Mitarbeiter bei dessen Ein- oder Austritt innerhalb (und nicht am Anfang oder am Ende) der Abrechnungsperiode.
[Deutsch] Abkürzungen
Ein paar Abkürzungen deren Bedeutung ich zum Teil erst viel zu spät im Leben gelernt habe… 🙂
| Haribo | Hans Riegel Bonn |
| Hanuta | Haselnuss Tafel |
| Adidas | Adolf (Adi) Dassler |
| Persil | Perborat & Silikat |
| Taff | Täglich, Aktuell, Frisch, Frech |
| Milka | Milchkakao |
| AEG | Aus Erfahrung Gut |
| Tetramino | aus vier Quadraten |
| Domino | aus zwei Quadraten |
| Monomino | aus einem Quadrat |
| Laser | Light amplification by stimulated emission of radiation |
| Radar | Radio detection and ranging |
| Unimog | Universal Motorgerät |
| Audi | lateinisch für “Horch!” nach Firmengründer August Horch |
| Taser | Thomas A. Swift’s Electric Rifle |
| LKW | Leber Käs Weckle (oder manchmal auch Last Kraft Wagen 😉 |
| Oliba | Oberlippenbart |
| Mufuti | Multifunktionstisch |
| Immobilien | weil sie nicht mobil, also immobil sind (lateinisch im-mobilis ‚unbeweglich‘) |
| Bischifo | Bildschirmfoto |
[SAPUI5] UI5 Web Components
https://blogs.sap.com/2020/12/21/using-ui5-web-components/
“With UI5 Web Components, developers can build the core logic of the application using these popular web frameworks, while using UI5 Web Components as the visual elements (controls).
- SAPUI5 – https://ui5.sap.com
- React – https://reactjs.org
- Angular – https://angular.io
- Vue.js – https://vuejs.org
Each of these web frameworks have different ways of handling data layer, persistence, binding, and integration with APIs, etc. but the nice thing about web components is that is integrates easily, regardless of the framework.”
[nodejs] APIs and Microservices Projects
These are my notes while doing the course APIs and Microservices on https://www.freecodecamp.org. I highly recommend it if you prefer to try things directly rather than watching videos.
Timestamp Microservice
https://repl.it/@nocin/boilerplate-project-timestamp#server.js
app.get("/api/timestamp/", (req, res) => {
res.json({ unix: Date.now(), utc: Date() });
});
app.get("/api/timestamp/:date?", (req, res) => {
//utc date?
let date = new Date(req.params.date)
if (date != "Invalid Date") {
res.json({unix: date.getTime(), utc: date.toUTCString()});
}
//unix timestamp?
const dateInt = parseInt(req.params.date);
date = new Date(dateInt).toUTCString();
if (date != "Invalid Date") {
res.json({unix: dateInt, utc: date});
}
//invalid input
res.json({ error: date });
});
Request Header Parser Microservice
https://repl.it/@nocin/boilerplate-project-headerparser#server.js
https://www.npmjs.com/package/express-useragent
https://www.npmjs.com/package/express-request-language
var useragent = require('express-useragent');
var cookieParser = require('cookie-parser');
var requestLanguage = require('express-request-language');
// stuff...
app.use(useragent.express());
app.use(cookieParser());
app.use(requestLanguage({
languages: ['en-US', 'zh-CN'],
cookie: {
name: 'language',
options: { maxAge: 24*3600*1000 },
url: '/languages/{language}'
}
}));
app.get("/api/whoami", (req, res) => {
res.json({"ipaddress": req.ip,
"language": req.language,
"software": req.useragent.source });
});
URL Shortener Microservice
https://repl.it/@nocin/boilerplate-project-urlshortener#server.js
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const app = express();
const bodyParser = require('body-parser');
const dns = require('dns');
// Basic Configuration
const port = process.env.PORT || 3000;
app.use(cors());
app.use('/public', express.static(`${process.cwd()}/public`));
app.get('/', function(req, res) {
res.sendFile(process.cwd() + '/views/index.html');
});
app.use(bodyParser.urlencoded({extended: false}));
let urls = [];
//POST
app.post("/api/shorturl/new", function(req, res) {
const getHostnameFromRegex = (url) => {
// run against regex
const matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
// extract hostname (will be null if no match is found)
return matches && matches[1];
}
hostname = getHostnameFromRegex(req.body.url);
console.log("Hostname: " + hostname);
// if no hostname found, return here
if (!hostname) res.json({ error: 'invalid url' });
// check if url is valid
dns.lookup(hostname, (error, addresses) => {
console.error(error);
console.log(addresses);
if (!error) {
let newUrl = { original_url : req.body.url, short_url : urls.length + 1};
urls.push(newUrl);
res.json(newUrl);
} else {
res.json({ error: 'invalid url' });
}
});
});
//GET
app.get('/api/shorturl/:num', function(req, res) {
for (let i = 0; i < urls.length; i++) {
console.log(urls[i].original_url);
if (urls[i].short_url == req.params.num) {
res.redirect(urls[i].original_url);
}
}
});
app.listen(port, function() {
console.log(`Listening on port ${port}`);
});
Exercise Tracker
https://repl.it/@nocin/boilerplate-project-exercisetracker#server.js
const express = require('express')
const app = express()
const cors = require('cors')
require('dotenv').config()
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
app.use(cors())
app.use(express.static('public'))
app.get('/', (req, res) => {
res.sendFile(__dirname + '/views/index.html')
});
const listener = app.listen(process.env.PORT || 3000, () => {
console.log('Your app is listening on port ' + listener.address().port)
})
//BodyParser
app.use(bodyParser.urlencoded({ extended: false }));
//DB connect
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });
const { Schema } = mongoose;
//User Schema
const userSchema = new Schema({
username: { type: String, required: true },
});
const User = mongoose.model("User", userSchema);
//Exercise Schema
const exerciseSchema = new Schema({
userId: Schema.Types.ObjectId,
description: { type: String, required: true },
duration: { type: Number, required: true },
date: { type: Date, default: Date.now }
});
const Exercise = mongoose.model("Exercise", exerciseSchema);
//POST user to DB
app.post("/api/exercise/new-user", (req, res) => {
let user = new User({ username: req.body.username });
user.save((err, data) => {
//console.log("created User: " + data);
if (err) return console.error(err);
res.json({ username: data.username, _id: data._id });
});
});
//GET all users from DB
app.get("/api/exercise/users", (req, res) => {
User.find((err, usersFound) => {
if (err) return console.error(err);
//console.error("users found: " + usersFound);
res.json(usersFound);
})
});
//POST exercise form data
app.post("/api/exercise/add", (req, res) => {
let exercise = new Exercise({
userId: req.body.userId,
description: req.body.description,
duration: req.body.duration,
date: req.body.date ? req.body.date : Date.now()
});
exercise.save((err, data) => {
//console.log("created exercise: " + data);
if (err) return console.error(err);
User.findById(exercise.userId, (err, userFound) => {
if (err) return console.error(err);
//console.log("userFound " + userFound.username);
res.json({
_id: data.userId,
username: userFound.username,
date: data.date.toDateString(),
duration: data.duration,
description: data.description
});
});
});
});
//GET exercise log
app.get("/api/exercise/log", (req, res) => {
console.log(req.query.userId);
console.log(req.query.from);
console.log(req.query.to);
console.log(req.query.limit);
let userId = req.query.userId;
let limit = Number(req.query.limit);
//create query filter
let filter = {};
filter.userId = userId;
if (req.query.from && req.query.to) {
let fromDate = new Date(req.query.from);
let toDate = new Date(req.query.to);
filter.date = { $gte: fromDate, $lte: toDate };
}
console.log("Filter " + JSON.stringify(filter));
const queryExercises = (done) => {
Exercise.find(filter)
.limit(limit)
.exec((err, exercices) => {
if (err) return console.error(err);
done(exercices);
})
};
const paseExercises = (exercices) => {
let logArray = [];
for (let i = 0; i < exercices.length; i++) {
var obj = exercices[i];
logArray.push({
description: obj.description,
duration: obj.duration,
date: obj.date.toDateString()
});
}
console.log(logArray);
User.findById(userId, (err, userFound) => {
if (err) return console.error(err);
let logger = {
_id: userId,
username: userFound.username,
count: logArray.length,
log: logArray
};
res.json(logger);
});
}
//Execute Query
queryExercises(paseExercises);
});
File Metadata Microservice
https://repl.it/@nocin/boilerplate-project-filemetadata#server.js
https://www.npmjs.com/package/multer
var express = require('express');
var cors = require('cors');
require('dotenv').config()
var multer = require('multer')
var upload = multer({ dest: 'uploads/' });
var app = express();
app.use(cors());
app.use('/public', express.static(process.cwd() + '/public'));
app.get('/', function (req, res) {
res.sendFile(process.cwd() + '/views/index.html');
});
const port = process.env.PORT || 3000;
app.listen(port, function () {
console.log('Your app is listening on port ' + port)
});
//POST
app.post('/api/fileanalyse', upload.single('upfile'), (req, res, next) => {
res.json({ name: req.file.originalname, type: req.file.mimetype, size: req.file.size });
})
[ABAP] Report Template
*&---------------------------------------------------------------------*
*& Report Z_REPORT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT Z_REPORT.
*-----------------------------------------------------------------------
* SELEKTIONSBILD
*-----------------------------------------------------------------------
*-----------------------------------------------------------------------
* Zeitpunkt INITIALIZATION.
*-----------------------------------------------------------------------
INITIALIZATION.
*----------------------------------------------------------------------
* Zeitpunkt AT SELECTION-SCREEN
*----------------------------------------------------------------------
AT SELECTION-SCREEN OUTPUT. "PBO
*-----------------------------------------------------------------------
* Zeitpunkt START-OF-SELECTION.
*-----------------------------------------------------------------------
START-OF-SELECTION.
*----------------------------------------------------------------------
* Zeitpunkt END-OF-SELECTION
*----------------------------------------------------------------------
END-OF-SELECTION.
[VSC] Extensions
Open-source registry for VS Code extensions: https://open-vsx.org/
Coden
https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer-2
https://marketplace.visualstudio.com/items?itemName=vscode-icons-team.vscode-icons
https://marketplace.visualstudio.com/items?itemName=mechatroner.rainbow-csv
Git
https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens
https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph
Markdown
https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one
https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint
https://marketplace.visualstudio.com/items?itemName=ban.spellright
Docker
https://marketplace.visualstudio.com/items?itemName=formulahendry.docker-explorer
WSL
https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl
[JavaScript] Extract hostname from string
https://stackoverflow.com/questions/8498592/extract-hostname-name-from-string
const getHostname = (url) => {
// use URL constructor and return hostname
return new URL(url).hostname;
}
let hostname = getHostname("https://google.com");
console.log(hostname); //google.com
[nodejs] MongoDB and Mongoose Challenges
These are my notes while doing the course APIs and Microservices on https://www.freecodecamp.org. I highly recommend it if you prefer to try things directly rather than watching videos.
MongoDB is a database that stores data records (documents) for use by an application. Mongo is a non-relational, “NoSQL” database. This means Mongo stores all associated data within one record, instead of storing it across many preset tables as in a SQL database.
Mongo’s use of JSON as its document storage structure makes it a logical choice when learning backend JavaScript. Accessing documents and their properties is like accessing objects in JavaScript.
Mongoose.js is an npm module for Node.js that allows you to write objects for Mongo as you would in JavaScript.
MongoDB Atlas is a MongoDB Database-as-a-Service platform.
Install and Set Up Mongoose
Add mongodb and mongoose to the project’s package.json.
"dependencies": {
"body-parser": "^1.15.2",
"dotenv": "^8.2.0",
"express": "^4.12.4",
"mongodb": "^3.6.4",
"mongoose": "^5.11.15"
},
Store your MongoDB Atlas database URI in a private .env file as MONGO_URI. Replace user and password.
MONGO_URI=mongodb+srv://<User>:<Password>@cluster0.xvsqx.mongodb.net/<dbname>?retryWrites=true&w=majority
Connect to the database using the following syntax:
const mongoose = require('mongoose');
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });
Create a Model
Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.
const { Schema } = mongoose;
const personSchema = new Schema({
name: { type: String, required: true },
age: Number,
favoriteFoods: [String]
});
const Person = mongoose.model("Person", personSchema);
Create and Save a Record of a Model
The done() function is a callback that tells us that we can proceed after completing an asynchronous operation such as inserting, searching, updating, or deleting. It’s following the Node convention, and should be called as done(null, data) on success, or done(err) on error.
const createAndSavePerson = (done) => {
let max = new Person({name: "Max", age: 31, favoriteFoods: ["Pasta"]});
max.save((err, data) => {
if (err) return console.error(err);
done(null, data)
});
};
Create Many Records with model.create()
var arrayOfPeople = [
{name: "Max", age: 31, favoriteFoods: ["Pasta"]},
{name: "Toni", age: 21, favoriteFoods: ["Pizza"]},
{name: "Paul", age: 34, favoriteFoods: ["Bolo", "Penne"]}
];
const createManyPeople = (arrayOfPeople, done) => {
Person.create(arrayOfPeople, (err, people) => {
if (err) return console.error(err);
done(null, people);
});
};
Use model.find() to Search Your Database
Model.find() accepts a query document (a JSON object) as the first argument, then a callback. It returns an array of matches.
const findPeopleByName = (personName, done) => {
Person.find({name: personName}, (err, personFound) => {
if (err) return console.error(err);
done(null, personFound);
})
};
Use model.findOne() to Return a Single Matching Document from Your Database
Model.findOne() behaves like Model.find(), but it returns only one document (not an array), even if there are multiple items.
const findOneByFood = (food, done) => {
Person.findOne({favoriteFoods: food}, (err, personFound) => {
if (err) return console.error(err);
done(null, personFound);
})
};
Use model.findById() to Search Your Database By _id
When saving a document, MongoDB automatically adds the field _id, and set it to a unique alphanumeric key.
const findPersonById = (personId, done) => {
Person.findById({_id: personId}, (err, personFound) => {
if (err) return console.error(err);
done(null, personFound);
})
};
Perform Classic Updates by Running Find, Edit, then Save
const findEditThenSave = (personId, done) => {
const foodToAdd = 'hamburger';
Person.findById(personId, (err, person) => {
if(err) return console.log(err);
person.favoriteFoods.push(foodToAdd);
person.save((err, updatedPerson) => {
if(err) return console.log(err);
done(null, updatedPerson)
})
})
};
Perform New Updates on a Document Using model.findOneAndUpdate()
Use the function parameter personName as the search key. Set the person’s age to 20.
Note: You should return the updated document. To do that, you need to pass the options document { new: true } as the 3rd argument to findOneAndUpdate(). By default, these methods return the unmodified object.
const findAndUpdate = (personName, done) => {
const ageToSet = 20;
Person.findOneAndUpdate({name: personName}, {age: ageToSet}, { new: true }, (err, updatedDoc) => {
if (err) return console.error(err);
done(null, updatedDoc)
})
};
Delete One Document Using model.findByIdAndRemove()
const removeById = (personId, done) => {
Person.findByIdAndRemove(personId, (err, personDeleted) => {
if (err) return console.error(err);
done(null, personDeleted)
})
};
Delete Many Documents with model.remove()
const removeManyPeople = (done) => {
const nameToRemove = "Mary";
Person.remove({name: nameToRemove}, (err, personsDeleted) => {
if (err) return console.error(err);
done(null, personsDeleted)
})
};
Chain Search Query Helpers to Narrow Search Results
const queryChain = (done) => {
const foodToSearch = "burrito";
Person.find({favoriteFoods: foodToSearch})
.sort({name: 1}) //sort bei name
.limit(2) //only 2 results
.select({age: 0}) //hide age
.exec((err, twoPersonFound) => {
if (err) return console.error(err);
done(null, twoPersonFound)
})
};
